如何截断csv文件到n行不读取整个文件



我有大的csv(12 gb),所以我不能在内存中读取它,我只需要100行并将其保存回来(截断)。java有这样的api吗?

其他答案从原始文件创建一个新文件。根据我的理解,您想要截断原始文件。使用RandomAccessFile:

可以很容易地做到这一点
try (RandomAccessFile file = new RandomAccessFile(FILE, "rw")) {
for (int i = 0;  i < N && file.readLine() != null; i++)
;  // just keep reading
file.setLength(file.getFilePointer());
}
需要注意的是,这将在N之后截断,这与N不一定是一回事,因为CSV文件可以有跨多行的行。例如,下面是一条CSV记录,它包含姓名、地址和电话号码,并且跨越多行:
Joe Bloggs, "1 Acacia Avenue,
Naboo Town,
Naboo", 01-234 56789

如果您确定所有的行只跨越一行,那么上面的代码将工作。但是,如果您的CSV行有可能跨越多行,那么您应该首先使用合适的CSV阅读器解析文件,找出在截断文件之前需要保留多少行。OpenCSV使这很容易:

final long numLines;
try (CSVReader csvReader = new CSVReader(new FileReader(FILE))) {
csvReader.skip(N);  // Skips N rows, not lines
numLines = csvReader.getLinesRead();  // Gives number of lines, not rows
}
try (RandomAccessFile file = new RandomAccessFile(FILE, "rw")) {
for (int i = 0; i < numLines && file.readLine() != null; i++)
;  // just keep reading
file.setLength(file.getFilePointer());
}

你应该流式传输文件:逐行读取

例如:

CSVReader reader = new CSVReader(new FileReader("myfile.csv"));
String [] nextLine;
// the readnext => Reads the next line from the buffer and converts to a string array.
while ((nextLine = reader.readNext()) != null) {
System.out.println(nextLine); 
}

如果您只需要100行,那么只需将文件的一小部分读入内存将是非常快速和便宜的。您可以使用标准库文件api很容易地实现这一点:

val firstHundredLines = File("test.csv").useLines { lines ->
lines.take(100).joinToString(separator = System.lineSeparator())
}
File("test.csv").writeText(firstHundredLines)

可能的解决方案

File file = new File(fileName);
// collect first N lines
String newContent = null;
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
newContent = reader.lines().limit(N).collect(Collectors.joining(System.lineSeparator()));
}
// replace original file with collected content
Files.write(file.toPath(), newContent.getBytes(), StandardOpenOption.TRUNCATE_EXISTING);