我正在寻找答案,但我找不到。有没有人有这种问题的解决方案。我有一组文本变量,我必须使用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
答案 0 :(得分:3)
您可能需要考虑使用Super CSV来编写CSV文件。除了处理嵌入式双引号和逗号之外,它提供了一系列writing implementations,可以从数组/列表,地图甚至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
答案 1 :(得分:1)
这是我解决问题的方法。由于低级随机访问文件机制,您不需要将整个数据保留在缓冲区。您仍然需要逐个加载记录:
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;
}
答案 2 :(得分:0)
我只是继续并假设你有一些自由来完成这项任务。据我所知,您不能将文本“插入”文件。您只能通过完全读取文件,在内存中更改它,然后将结果写回文件来完成。
因此,如果您在内存中反转数据结构然后编写它会更好。如果您的数据对象是一个矩阵,只需转置它,使其符合您要写的格式。
答案 3 :(得分: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();
}
答案 4 :(得分:0)
根据您在发生错误时不丢失任何数据的要求,也许您应该重新考虑设计并使用嵌入式数据库(在Embedded java databases处讨论了各种嵌入式数据库的优点)。您只需要在数据库中使用一个表。
我建议这样做,因为在您的原始问题中,您似乎正在尝试使用CSV文件,如数据库,您可以按任意顺序更新任何行的列。在这种情况下,为什么不咬紧牙关并使用真正的数据库。
无论如何,一旦填写了表的所有列和行,就将数据库导出为“文本文件顺序”中的CSV文件row1-col1,row1-col2 ... row2-col1等。
如果在构建数据库期间发生错误,或者至少导出CSV文件,您仍然可以获得上一次运行的所有数据,并且可以再试一次。