CSV เป็น HTML Converter
ฉันเขียนโปรแกรมเล็ก ๆ น้อย ๆ ที่แปลงไฟล์ CSV เป็น HTML-Table มันทำงานตามวัตถุประสงค์ของฉัน แต่มีบางส่วนในโค้ดของฉันที่สามารถเขียนได้สะอาดกว่านี้ไหม คุณสามารถปรับปรุงประสิทธิภาพได้หรือไม่? อาจมีข้อบกพร่องหรือไม่? ฉันค้นหาจุดบกพร่องและโชคดีที่ไม่พบบางส่วน
Postscript
บางทีฉันควรให้ข้อมูลพื้นฐานบางอย่าง: ฉันกำลังทำงานเกี่ยวกับเอกสารฐานข้อมูลที่ฉันเขียนเป็นเอกสาร HTML เพราะฉันไม่ชอบเอกสาร Word อย่างไรก็ตามการสร้างคำอธิบายแบบตารางของคอลัมน์ที่มีแท็กหลายสิบแท็กนั้นเจ็บปวด นั่นคือเหตุผลที่ฉันเขียนสคริปต์นี้: ตอนนี้ฉันต้องส่งออกข้อมูลตารางเป็น CSV เท่านั้นและสามารถแปลงได้โดยตรงโดยไม่ต้องป้อนแท็กจำนวนมากด้วยตัวเอง นี่คือเหตุผลที่ไม่มี 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
ExampleInput.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>
คำตอบ
ใช้งานได้ดีค้นหาคำแนะนำของฉันแบบอินไลน์
เขียนได้สะอาดมากขึ้น?
- ชั้นเรียน
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=",";
- ระบุข้อความผู้ใช้และออกในกรณีของข้อยกเว้น I / O ตัวอย่างเช่น:
} 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 กล่าวไว้ตรรกะการตรวจสอบอินพุตจำเป็นต้องพิจารณาเมื่อไม่มีข้อโต้แย้งหนึ่งสองข้อหรือมากกว่า
CSVReader
การอ่านไฟล์ CSV อาจเป็นงานที่ซับซ้อน แม้ว่าไฟล์ CSV จำนวนมากจะเป็นเพียงค่าที่คั่นด้วยเครื่องหมายจุลภาค แต่หากค่ามีเครื่องหมายจุลภาคจะถูกล้อมรอบด้วยเครื่องหมายคำพูดคู่และหากค่ามีเครื่องหมายคำพูดคู่คำพูดคู่จะเพิ่มเป็นสองเท่า
หากต้องการจัดการสิ่งเหล่านี้ให้เป็นเพียงไฟล์ CSV พื้นฐานคุณควรใช้ไลบรารี CSV เช่นOpenCSV (com.opencsv: opencsv: 5.0) หรือApache Commons CSV (org.apache.commons: commons-csv: 1.7)
HTML
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 prolog
- สำหรับแต่ละบรรทัดที่อ่านจากไฟล์ CSV:
- จัดรูปแบบและเขียนบรรทัดไปยังไฟล์ HTML
- เขียน HTML epilog
ยังไม่ได้ทดสอบเขียนโค้ดจากสะโพกโดยไม่ต้องจัดการการอ้างอิงใน 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
คุณอาจต้องการพิจารณาสร้างตัวแปล CSV เป็น XML
ผลลัพธ์ 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>
จากนั้นคุณสามารถใช้XSLT Stylesheetเพื่อแปล XML เป็น HTML ซึ่งอาจเป็นในเบราว์เซอร์โดยไม่ต้องเขียน HTML ลงในไฟล์
ได้NullPointerExceptionที่ไลน์if (args[0].equals...
โปรดตรวจสอบargsขนาดอินพุตและnullifyingก่อนดำเนินการเข้าถึงดัชนี / รายการใด ๆ
ใช่ซึ่งargsอาจnullเรียกได้ว่าคลาสอื่นที่โหลดไว้ หรือว่างเปล่าหากผู้ใช้ลืมตั้งค่าargs.
ไฟล์บัฟเฟอร์
ฉันคิดว่าการแคชไฟล์ทั้งหมดในหน่วยความจำแล้วประมวลผลเป็นความคิดที่ดีสำหรับกรณีของคุณเนื่องจากแต่ละบรรทัดที่คุณอ่านคุณสามารถประมวลผลและเขียนและดำเนินการต่อในบรรทัดถัดไป ( ตามการประมวลผลแบบ Line By Line ที่กล่าวถึงโดย AJNeufeld)
หักคอลัมน์ (ตัวคั่น)
โดยทั่วไปการแบ่งข้อมูลคอลัมน์โดยใช้lines.get(i).replaceAll(",",...)จะเสียเนื่องจากข้อมูลจะมี,เป็นเนื้อหา
เมื่อพิจารณาถึงบรรทัดPorsche,"991,991.2,992",70ที่โค้ดของคุณ (และแม้แต่โค้ดที่ AJNeufeld ให้มา) จะล้มเหลวเนื่องจาก991,991.2,992เป็นค่าเดียวและ""มีไว้เพื่อบอกตัวแยกวิเคราะห์ข้อมูลที่ถูก Escape จะอยู่ข้างหน้า
โดยส่วนตัวแล้วฉันขอแนะนำให้ใช้กระบวนการแยกวิเคราะห์แบบ char-by-char ซึ่งช่วยให้คุณสามารถข้ามสิ่งใด ๆ ที่,เป็นตัวคั่นเมื่อคุณไปถึงช่องเปิด"จนถึง"คู่ที่สิ้นสุด
Chars ที่ไม่คาดคิด
นอกจากนี้ยังพิจารณาที่จะยืนยันข้ามหรือแปลงอักขระที่ไม่คาดคิด ตัวอย่างเช่นการแปลง a NULL( \0) char เป็น0x00หรือแสดงคำเตือนแล้วข้ามไป
ลืมไฟล์
ฉันขอแนะนำว่าอย่าล็อกแอปของคุณให้อ่านจากไฟล์และบันทึกลงในแอป หลายครั้งSTDINและSTDOUTเป็นวิธีที่น่ายินดีมากขึ้น
ฉันขอแนะนำให้รองรับทั้งไฟล์และSTDIN. ยกตัวอย่างเช่นการใช้งานมีชุด-finสำหรับไฟล์อินพุตในการโต้เถียงหรือที่จะแจ้งให้เครื่องมืออ่านจาก-stdinSTDIN
กำลังตรวจสอบไฟล์
การตรวจสอบไฟล์ (ทั้งเข้า / ออก) ก่อนประมวลผลไฟล์ก็จะดีเช่นกัน เพื่อให้แน่ใจว่าสามารถเข้าถึงได้
การยืนยัน
การล้างผลลัพธ์ (หรือพร้อมต์ / ตั้งค่าได้) ในขณะที่มีข้อยกเว้น IO ที่ไม่คาดคิดในระหว่างกระบวนการอาจดีเช่นกัน
หวังว่าจะช่วยได้