CSV को HTML कन्वर्टर

Sep 08 2020

मैंने एक छोटा प्रोग्राम लिखा है जो CSV- फाइल को HTML- टेबल में बदलता है। यह मेरे उद्देश्यों के लिए काम करता है। लेकिन क्या मेरे कोड में ऐसे हिस्से हैं जिन्हें अधिक साफ लिखा जा सकता है? क्या आप प्रदर्शन में सुधार कर सकते हैं? क्या शायद कोई कीड़े हैं? मैंने बग खोजे और सौभाग्य से मुझे कुछ नहीं मिला।

परिशिष्ट भाग

शायद मुझे कुछ पृष्ठभूमि की जानकारी प्रदान करनी चाहिए: मैं एक डेटाबेस दस्तावेज पर काम कर रहा हूं जिसे मैं एक HTML दस्तावेज़ के रूप में लिख रहा हूं, क्योंकि मुझे वर्ड-डॉक्यूमेंट पसंद नहीं हैं। हालांकि, दर्जनों टैग के साथ कॉलम का एक सारणीबद्ध विवरण बनाना दर्दनाक है। यही कारण है कि मैंने यह स्क्रिप्ट लिखी है: अब मुझे केवल सीएसवी के रूप में टेबल की जानकारी का निर्यात करना है और इसे स्वयं कई टैग्स दर्ज किए बिना सीधे रूपांतरित कर सकते हैं। यही कारण है कि कोई HTML और बॉडी टैग नहीं हैं: बनाई गई तालिकाओं को अलग-अलग HTML दस्तावेज़ नहीं होना चाहिए, लेकिन एक एकल, बड़े HTML दस्तावेज़ के कुछ हिस्से।

CsvToHtmlTable.java

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileWriter;
import java.util.List;
import java.util.ArrayList;

public class CsvToHtmlTable {
    public static void main(String[] args) {
        // print info and show user how to call the program if needed
        System.out.println("This program is tested only for UTF-8 files.");
        if (args[0].equalsIgnoreCase("help") || args[0].equalsIgnoreCase("-help") || args.length != 2) {
            System.out.println("java CsvToHtmlTable <input file> <output file>");
            System.out.println("Example: java CsvToHtmlTable nice.csv nice.html");
            System.exit(0);
        }
        
        String csvFile = args[0];
        String outputFile = args[1];
        
        // read lines of csv to a string array list
        List<String> lines = new ArrayList<String>();
        try (BufferedReader reader = new BufferedReader(new FileReader(csvFile))) {
            String currentLine;
            while ((currentLine = reader.readLine()) != null) {
                lines.add(currentLine);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        //embrace <td> and <tr> for lines and columns
        for (int i = 0; i < lines.size(); i++) {
            lines.set(i, "<tr><td>" + lines.get(i) + "</td></tr>");
            lines.set(i, lines.get(i).replaceAll(",", "</td><td>"));
        }
        
        // embrace <table> and </table>
        lines.set(0, "<table border>" + lines.get(0));
        lines.set(lines.size() - 1, lines.get(lines.size() - 1) + "</table>"); 
        
        // output result
        try (FileWriter writer = new FileWriter(outputFile)) {
            for (String line : lines) {
                writer.write(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

प्रोग्राम को कैसे कॉल करें:

java CsvToHtmlTable ExampleInput.csv ExampleOutput.html

उदाहरणInput.csv

Name,Vorname,Alter
Ulbrecht,Klaus Dieter,12
Meier,Bertha,102

ExampleOutput.html

<table border><tr><td>Name</td><td>Vorname</td><td>Alter</td></tr>
<tr><td>Ulbrecht</td><td>Klaus Dieter</td><td>12</td></tr>
<tr><td>Meier</td><td>Bertha</td><td>102</td></tr></table>

जवाब

4 Marc Sep 09 2020 at 03:25

अच्छा कार्यान्वयन, मेरे सुझाव इनलाइन पाएं।


अधिक साफ लिखा जा सकता है?

  • कक्षा java.nio.file.Filesमें कुछ आसान तरीके हैं जिनका आप उपयोग कर सकते हैं:
lines = Files.readAllLines(Paths.get(csvFile), StandardCharsets.UTF_8);
//..
Files.write(Paths.get(outputFile), lines);
  • सीमांकक चरित्र के लिए एक स्थिरांक बनाने पर विचार करें। कुछ CSV फाइलें कॉमास ;आदि मानों को संभालने के लिए सीमांकित की जाती हैं।
public static final String DELIMITER_CHAR=",";
  • उदाहरण के लिए, आई / ओ अपवाद के मामले में एक उपयोगकर्ता संदेश और निकास प्रदान करें:
} catch (IOException e) {
    System.out.println("Error reading input file: "+e.getMessage());
    System.exit(1);
}
  • लाइनों को एक विधि में बदलने के लिए तर्क को अलग करें, ताकि परीक्षण और पुन: उपयोग करना आसान हो। उदाहरण के लिए:
public class CsvToHtmlTable{
    public static List<String> convert(List<String> lines){/**/}
    public static void main(String[] args){/**/}
}

क्या आप प्रदर्शन में सुधार कर सकते हैं?

इस कार्यान्वयन की सीमा स्मृति बाधा है। यदि इनपुट फ़ाइल बड़ी है, तो पूरी फ़ाइल उपलब्ध मेमोरी में फिट नहीं हो सकती है।

आपका मामला नहीं हो सकता है, लेकिन यदि आपको बड़ी फ़ाइलों को संभालने की आवश्यकता है, तो लाइन द्वारा फ़ाइल लाइन को पढ़ने और लिखने पर विचार करें।


क्या शायद कोई कीड़े हैं?

  • जांचें कि क्या इनपुट फ़ाइल खाली है, अन्यथा lines.set(0,..)विफल रहता है
  • जैसा कि @ Doi9t ने उल्लेख किया है, इनपुट सत्यापन तर्क पर विचार करने की आवश्यकता है जब कोई तर्क, एक, दो या अधिक नहीं हो।
5 AJNeufeld Sep 09 2020 at 03:02

CSVReader

CSV फ़ाइल पढ़ना एक जटिल कार्य हो सकता है। जबकि कई CSV फाइलें सिर्फ कॉमा-सेपरेट-वैल्यू होती हैं, अगर किसी वैल्यू में कॉमा होता है, तो यह डबल कोट्स से घिरा होगा, और अगर वैल्यू में डबल कोट्स होते हैं, तो डबल कोट्स खुद ही डबल हो जाते हैं।

इन अधिक को संभालने के लिए कि बस एक मूल CSV फाइलें, आपको वास्तव में एक CSV लाइब्रेरी का उपयोग करना चाहिए, जैसे OpenCSV (com.opencsv: opencsv: 5.0) या Apache Commons CSV (org.apache.commons: commons-csv: 1.7)।

एचटीएमएल

मान्य HTML

आपका कोड अनिवार्य रूप से सिर्फ लिखता है <table>...table data...</table>। यह उचित HTML नहीं है। आप <html>...</html>संपूर्ण दस्तावेज़ और <body>...</body>सामग्री के आसपास टैग गायब कर रहे हैं । तुम भी शायद एक होना चाहिए <head>...</head>, शायद एक अच्छा के साथ <title>...</title>।

भागने

अपनी CSV डेटा किसी भी विशेष वर्ण, जैसे <, >, और &, आप वास्तव में उन्हें उत्पन्न HTML तालिका में पलायन करना होगा।

टेबल हेडिंग

ऐसा लगता है कि आपकी तालिका की पहली पंक्ति में शीर्षक हैं, डेटा नहीं। पहली तालिका पंक्ति को संभवतः <th>...</th>टैग के बजाय टैग के साथ स्वरूपित किया जाना चाहिए <td>...</td>।

लाइन द्वारा लाइन प्रसंस्करण

आप संपूर्ण CSV फ़ाइल को मेमोरी में पढ़ रहे हैं, और केवल जब इसे इसकी संपूर्णता में लोड किया गया है, तो आप इसे वापस HTML के रूप में लिख रहे हैं। यह बहुत स्मृति गहन है, खासकर अगर CSV फ़ाइल बहुत बड़ी है!

इसके बजाय, आप कर सकते हैं:

  • CSV खोलें
  • HTML फ़ाइल खोलें
  • HTML प्रस्तावना लिखें
  • CSV फ़ाइल से पढ़ी गई प्रत्येक पंक्ति के लिए:
    • प्रारूप और HTML फ़ाइल के लिए लाइन लिखें
  • HTML एपिलॉग लिखें

CSV में उद्धृत किए बिना या आउटपुट में किसी भी HTML संस्थाओं से बचने के बिना, कूल्हे से बिना कोडिंग

        try (BufferedReader reader = new BufferedReader(new FileReader(csvFile));
             FileWriter writer = new FileWriter(outputFile)) {

            writer.write("<html><body><table border>\n");

            String currentLine;
            while ((currentLine = reader.readLine()) != null) {
                writer.write("<tr>");

                for(String field: currentLine.split(","))
                    writer.write("<td>" + field + "</td>");

                writer.write("</tr>\n");
            }

            writer.write("</table></body></html>\n");

        } catch (IOException e) {
            e.printStackTrace();
        }

XML और XSLT

आप XML अनुवादक को CSV बनाने पर विचार कर सकते हैं।

आपका XML आउटपुट जैसा दिख सकता है:

<data input-file='ExampleInput.csv'>
  <person>
    <Name>Ulbrecht</Name>
    <Vorname>Klaus Dieter</Vorname>
    <Alter>12</Alter>
  </person>
  <person>
    <Name>Meier</Name>
    <Vorname>Bertha</Vorname>
    <Alter>102</Alter>
  </person>
</data>

और फिर आप XML को HTML में ट्रांसलेट करने के लिए XSLT स्टाइल्सशीट का उपयोग कर सकते हैं , संभवतः एक ब्राउज़र में बिना किसी फ़ाइल को HTML लिखने के।

3 Noname Sep 10 2020 at 23:23

NullPointerExceptionलाइन में संभवif (args[0].equals...

कृपया इनपुट argsआकार की जाँच करें और nullifyingकिसी भी इंडेक्स / आइटम तक पहुँचने से पहले।
हाँ, यह argsहो सकता है null, जैसा कि एक अन्य लोडेड क्लास द्वारा कहा जाता है। या खाली है, अगर उपयोगकर्ता सेट करना भूल जाता है args।

बफरिंग फाइल

मुझे लगता है कि पूरी फ़ाइल को मेमोरी में कैशिंग करना, और फिर इसे संसाधित करना आपके मामले के लिए एक अच्छा विचार है, जैसा कि आप पढ़ी गई प्रत्येक पंक्ति, आप बस प्रक्रिया कर सकते हैं, और इसे लिख सकते हैं, और अगली पंक्ति के लिए आगे बढ़ सकते हैं। ( AJNeufeld द्वारा उल्लिखित लाइन बाय लाइन प्रोसेसिंग के रूप में)

टूटा हुआ स्तंभ (परिसीमन) बंटवारा

मूल रूप से, स्तंभ डेटा का उपयोग करते हुए विभाजन lines.get(i).replaceAll(",",...)टूट गया है, क्योंकि डेटा में ही ,सामग्री होगी।

एक पंक्ति को ध्यान में रखते हुए Porsche,"991,991.2,992",70जहां आपका कोड (और यहां तक ​​कि AJNeufeld द्वारा प्रदान किया गया) विफल हो जाएगा, क्योंकि 991,991.2,992एक मूल्य है, और उन लोगों ""को पार्सर बताने के लिए हैं, बच गए डेटा आगे हैं।

तो व्यक्तिगत रूप से, मेरा सुझाव है कि एक चार-दर-चरण पार्सिंग प्रक्रिया के लिए जाएं, जिससे आप किसी भी ,सीमांकक के रूप में छोड़ सकते हैं जब आप "अपनी अंतिम "जोड़ी को खोलते हैं ।

अनपेक्षित प्रभार

इसके अलावा या तो जोर देने, छोड़ने या किसी भी अप्रत्याशित वर्ण को बदलने पर विचार करना। उदाहरण के लिए NULL( \0) चार को 0x00चेतावनी में परिवर्तित करना या उसे छोड़ना।

फ़ाइलें भूल जाओ

मेरा सुझाव है, अपने एप्लिकेशन को केवल फ़ाइलों से पढ़ने के लिए लॉक न करें, और उन्हें सहेजें। कई बार STDIN, और STDOUTअधिक स्वागत योग्य तरीके हैं।

मैं एक फ़ाइल और दोनों से समर्थन करने का सुझाव देता हूं STDIN। उदाहरण के लिए, उपयोग को -finफ़ाइल-इनपुट के लिए तर्क में सेट करना है, या -stdinसे पढ़े गए टूल को सूचित करना है STDIN।

फ़ाइलें जाँच रहा है

फ़ाइल संसाधित करने से पहले (दोनों / बाहर) फ़ाइलों की जाँच करना बहुत अच्छा होगा। यह सुनिश्चित करने के लिए कि वे सुलभ हैं।

अभिकथन

सफाई (या शीघ्र / सेट करने योग्य) परिणाम, जबकि प्रक्रिया के दौरान एक अप्रत्याशित IO अपवाद भी अच्छा हो सकता है।

आशा है कि इससे सहायता मिलेगी।