5

我正在为此寻找答案,但没有找到。有没有人有这种问题的解决方案。我有一组文本变量,我必须使用 Java 将它们写入 .CSV 文件。我目前正在使用 JavaScript 做一个需要 Java 的项目。这是我现在拥有的一个功能,它可以很好地完成工作并将文本逐行写入.CSV。

function writeFile(filename, data)
{
   try
   { 

      //write the data

      out = new java.io.BufferedWriter(new java.io.FileWriter(filename, true));
      out.newLine();
      out.write(data);
      out.close();
      out=null;
   }
   catch(e)   //catch and report any errors
   {
      alert(""+e);
   }
}

但是现在我必须像下面的示例一样逐个编写部分文本。

first0,second0,third0
first1,second1,third1
first2,second2,third2
.
.
.
first9,second9,third9

所以算法是这样的。该函数用逗号写入first0,然后转到下一行写入first1,转到下一行写入first2,如此一来直到first9。完成该部分后,脚本转到文件开头并在逗号后面写入 second0,转到下一行并在逗号后面写入 second1,依此类推。你明白了。

所以现在我需要java

4

5 回答 5

4

您可能要考虑使用Super CSV来编写 CSV 文件。除了处理嵌入的双引号和逗号转义之外,它还提供了一系列从数组/列表、映射甚至 POJO 写入的编写实现,这意味着您可以轻松地尝试您的想法。

如果您想让它变得非常简单,您可以将 CSV 文件组装成一个二维数组。这允许先将其组装成列,然后在准备好时将整个内容写入 CSV。

package example;

import java.io.FileWriter;
import java.io.IOException;

import org.supercsv.io.CsvListWriter;
import org.supercsv.io.ICsvListWriter;
import org.supercsv.prefs.CsvPreference;

public class ColumnFirst {

    public static void main(String[] args) {

        // you can assemble this 2D array however you want
        final String[][] csvMatrix = new String[3][3];
        csvMatrix[0][0] = "first0";
        csvMatrix[0][1] = "second0";
        csvMatrix[0][2] = "third0";
        csvMatrix[1][0] = "first1";
        csvMatrix[1][1] = "second1";
        csvMatrix[1][2] = "third1";
        csvMatrix[2][0] = "first2";
        csvMatrix[2][1] = "second2";
        csvMatrix[2][2] = "third2";

        writeCsv(csvMatrix);

    }

    private static void writeCsv(String[][] csvMatrix) {

        ICsvListWriter csvWriter = null;
        try {
            csvWriter = new CsvListWriter(new FileWriter("out.csv"), 
                CsvPreference.STANDARD_PREFERENCE);

            for (int i = 0; i < csvMatrix.length; i++) {
                csvWriter.write(csvMatrix[i]);
            }

        } catch (IOException e) {
            e.printStackTrace(); // TODO handle exception properly
        } finally {
            try {
                csvWriter.close();
            } catch (IOException e) {
            }
        }

    }

}

输出:

first0,second0,third0
first1,second1,third1
first2,second2,third2
于 2012-09-24T00:20:26.860 回答
2

这是我对问题的解决方案。由于低级随机访问文件机制,您不需要将整个数据保存在缓冲区中。您仍然需要一一加载您的记录:

package file.csv;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.List;

public class CsvColumnWriter {

    public static void main(String args[]) throws Exception{

        CsvColumnWriter csvWriter = new CsvColumnWriter(new File("d:\\csv.txt"), new File("d:\\csv.work.txt"), 3);

        csvWriter.writeNextCol(Arrays.asList(new String[]{"first0", "first1", "first2"}));
        csvWriter.writeNextCol(Arrays.asList(new String[]{"second0", "second1", "second2"}));
        csvWriter.writeNextCol(Arrays.asList(new String[]{"third0", "third1", "third2"}));

    }

    public void writeNextCol(List<String> colOfValues) throws IOException{
        // we are going to create a new target file so we have to first 
        // create a duplicated version
        copyFile(targetFile, workFile);

        this.targetStream = new BufferedOutputStream(new FileOutputStream(targetFile));

        int lineNo = 0;

        for(String nextColValue: colOfValues){

            String nextChunk = nextColValue + ",";

            // before we add the next chunk to the current line, 
            // we must retrieve the line from the duplicated file based on its the ofset and length 
            int lineOfset = findLineOfset(lineNo);  

            workRndAccFile.seek(lineOfset);

            int bytesToRead = lineInBytes[lineNo];
            byte[] curLineBytes = new byte[bytesToRead];
            workRndAccFile.read(curLineBytes);

            // now, we write the previous version of the line fetched from the
            // duplicated file plus the new chunk plus a 'new line' character
            targetStream.write(curLineBytes);
            targetStream.write(nextChunk.getBytes());
            targetStream.write("\n".getBytes());

            // update the length of the line
            lineInBytes[lineNo] += nextChunk.getBytes().length; 

            lineNo++;
        }

        // Though I have not done it myself but obviously some code should be added here to care for the cases where 
        // less column values have been provided in this method than the total number of lines

        targetStream.flush();
        workFile.delete();

        firstColWritten = true;
    }

    // finds the byte ofset of the given line in the duplicated file
    private int findLineOfset(int lineNo) {  
        int ofset = 0;
        for(int i = 0; i < lineNo; i++)
            ofset += lineInBytes[lineNo] + 
                (firstColWritten? 1:0); // 1 byte is added for '\n' if at least one column has been written
        return ofset;
    }

    // helper method for file copy operation
    public static void copyFile( File from, File to ) throws IOException {
            FileChannel in = new FileInputStream( from ).getChannel();
            FileChannel out = new FileOutputStream( to ).getChannel();
            out.transferFrom( in, 0, in.size() );
    }

    public CsvColumnWriter(File targetFile, File workFile, int lines) throws Exception{
        this.targetFile = targetFile;
        this.workFile = workFile;

        workFile.createNewFile();

        this.workRndAccFile = new RandomAccessFile(workFile, "rw");

        lineInBytes = new int[lines];
        for(int i = 0; i < lines; i++)
            lineInBytes[i] = 0;

        firstColWritten = false;
    }

    private File targetFile;
    private File workFile;

    private int[] lineInBytes;
    private OutputStream targetStream;
    private RandomAccessFile workRndAccFile;
    private boolean firstColWritten;

}
于 2012-09-24T02:57:27.777 回答
0

我只是继续前进,并假设您有一些自由来完成这项任务。据我所知,您不能将文本“插入”到文件中。您只能通过完全读取文件,在内存中更改它,然后将结果写回文件来做到这一点。

所以如果你在内存中反转你的数据结构然后写它会更好。如果您的数据对象是一个矩阵,只需将其转置,使其符合您要编写的格式。

于 2012-09-23T23:14:02.743 回答
0

这个怎么样

        Scanner input = new Scanner(System.in);
        String[] lines = new String[9];

        for (int j = 0; j < 2; j++) {
            for (int i = 0; i < 9; i++) {
                lines[i] += (String) input.nextLine() + ",";
            }
        }
        for (int i = 0; i < 9; i++) {
            lines[i] += (String) input.nextLine();
        }
于 2012-09-23T23:31:53.473 回答
0

基于您在发生错误时不丢失任何数据的要求,也许您应该重新考虑设计并使用嵌入式数据库(嵌入式 java 数据库中讨论了各种嵌入式数据库的优点)。您只需要数据库中的一个表。

我建议这样做,因为在您最初的问题中,听起来您正在尝试使用像数据库这样的 CSV 文件,您可以在其中以任何顺序更新任何行的列。在那种情况下,为什么不硬着头皮使用真正的数据库。

无论如何,一旦您填写了表格的所有列和行,将数据库以“文本文件顺序”row1-col1、row1-col2 ... row2-col1 等导出到 CSV 文件。

如果在构建数据库或导出 CSV 文件的过程中发生错误,至少您仍将拥有上次运行的所有数据,并且可以重试。

于 2012-09-24T00:03:51.300 回答