package edu.stanford.nlp.sempre.tables.serialize; import java.io.*; import au.com.bytecode.opencsv.CSVWriter; import edu.stanford.nlp.sempre.tables.*; import fig.basic.LogInfo; /** * Write a table in either CSV or TSV format. * All IOExceptions are thrown as RuntimeException. * * For CSV, this class is just a wrapper for OpenCSV. * Escape sequences for CSV: * - \\ => \ * - \" or "" => " * Each cell can be quoted inside "...". Embed newlines must be quoted. * * For TSV, each line must represent one table row (no embed newlines). * Escape sequences for TSV (custom): * - \n => [newline] * - \\ => \ * - \p => | * * @author ppasupat */ public class TableWriter { public final TableKnowledgeGraph graph; public TableWriter(TableKnowledgeGraph graph) { this.graph = graph; } /** * If out is null, log using LogInfo. Otherwise, print line to out. */ private void write(PrintWriter out, String stuff) { if (out == null) LogInfo.logs("%s", stuff); else out.println(stuff); } // ============================================================ // CSV // ============================================================ public void writeCSV() { writeCSVActual(null); } public void writeCSV(PrintWriter out) { writeCSVActual(out); } public void writeCSV(String filename) { try (PrintWriter out = new PrintWriter(filename)) { writeCSVActual(out); } catch (IOException e) { throw new RuntimeException(e); } } private void writeCSVActual(PrintWriter out) { try (CSVWriter writer = new CSVWriter(out)) { String[] record = new String[graph.numColumns()]; // Print header for (int j = 0; j < record.length; j++) record[j] = graph.getColumn(j).originalString; writer.writeNext(record); // Print other rows for (int i = 0; i < graph.numRows(); i++) { for (int j = 0; j < record.length; j++) record[j] = graph.getCell(i, j).properties.originalString; writer.writeNext(record); } } catch (IOException e) { throw new RuntimeException(e); } } // ============================================================ // TSV // ============================================================ public void writeTSV() { writeTSVActual(null); } public void writeTSV(PrintWriter out) { writeTSVActual(out); } public void writeTSV(String filename) { try (PrintWriter out = new PrintWriter(filename)) { writeTSVActual(out); } catch (IOException e) { throw new RuntimeException(e); } } private void writeTSVActual(PrintWriter out) { String[] record = new String[graph.numColumns()]; // Print header for (int j = 0; j < record.length; j++) record[j] = StringNormalizationUtils.escapeTSV(graph.getColumn(j).originalString); write(out, String.join("\t", record)); // Print other rows for (int i = 0; i < graph.numRows(); i++) { for (int j = 0; j < record.length; j++) record[j] = StringNormalizationUtils.escapeTSV(graph.getCell(i, j).properties.originalString); write(out, String.join("\t", record)); } } // ============================================================ // Human Readable Format // ============================================================ public void log() { writeHumanReadableActual(null); } public void writeHumanReadable() { writeHumanReadableActual(null); } public void writeHumanReadable(PrintWriter out) { writeHumanReadableActual(out); } public void writeHumanReadable(String filename) { try (PrintWriter out = new PrintWriter(filename)) { writeHumanReadableActual(out); } catch (IOException e) { throw new RuntimeException(e); } } private void writeHumanReadableActual(PrintWriter out) { int LIMIT = 20, numColumns = graph.numColumns(); // Measure widths int[] widths = new int[numColumns]; for (int i = 0; i < numColumns; i++) widths[i] = Math.max(widths[i], graph.getColumn(i).originalString.length()); for (TableRow row : graph.rows) for (int j = 0; j < numColumns; j++) widths[j] = Math.max(widths[j], row.children.get(j).properties.originalString.length()); for (int i = 0; i < numColumns; i++) widths[i] = Math.max(1, Math.min(widths[i], LIMIT)); // Print! { StringBuilder sb = new StringBuilder("|"); for (int i = 0; i < numColumns; i++) sb.append(String.format(" %-" + widths[i] + "s", cutoff(graph.columns.get(i).originalString, LIMIT))).append(" |"); write(out, sb.toString()); } for (TableRow row : graph.rows) { StringBuilder sb = new StringBuilder("|"); for (int i = 0; i < numColumns; i++) sb.append(String.format(" %-" + widths[i] + "s", cutoff(row.children.get(i).properties.originalString, LIMIT))).append(" |"); write(out, sb.toString()); } } private String cutoff(String x, int limit) { x = x.replace('\n', ' '); if (x.length() < limit) return x; return x.substring(0, limit - 3) + "..."; } }