Java中如何设置.csv文件的最大大小,超限时自动删除旧数据追加新内容
解决方案
你需要实现的是滚动式CSV写入逻辑,完全可以做到不缓存全文件内容,内存占用极低,以下是具体实现思路和可直接运行的代码:
核心逻辑
同时兼容行限制和大小限制两个触发条件,触发后自动删除最旧的第一条数据:
- 写入前先判断CSV文件是否存在,不存在则先写入表头
- 每次写入新数据前,分别统计当前文件的行数和文件大小,两个条件任意一个触达上限就启动滚动逻辑
- 滚动逻辑不需要把全文件读进内存,通过临时文件逐行读写:先写表头,跳过最旧的第一条数据,复制剩余所有旧数据,最后追加新数据,再用临时文件覆盖原文件即可
优化后可运行代码
import java.io.*; import java.time.LocalDate; import java.time.LocalTime; public class RollingCsvWriter { // 可自定义配置参数 private static final int MAX_DATA_ROWS = 1000; // 最大数据行数(不含表头) private static final long MAX_FILE_SIZE = 2 * 1024 * 1024; // 最大文件大小2MB private static final String FILE_PATH = "myCSV.csv"; private static final String CSV_HEADER = "Date; Time\n"; public static void main(String[] args) { File csvFile = new File(FILE_PATH); // 首次创建文件时写入表头,避免重复写表头 if (!csvFile.exists()) { try (FileWriter writer = new FileWriter(csvFile)) { writer.append(CSV_HEADER); } catch (IOException e) { e.printStackTrace(); return; } } while (true) { try { writeNewRecord(csvFile, LocalDate.now() + ";" + LocalTime.now() + "\n"); Thread.sleep(60000); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } } private static void writeNewRecord(File csvFile, String newLine) throws IOException { long currentFileSize = csvFile.length(); int currentTotalRows = countTotalRows(csvFile); // 未达限制直接追加写入 if (currentTotalRows < MAX_DATA_ROWS + 1 && currentFileSize + newLine.getBytes().length < MAX_FILE_SIZE) { try (FileWriter writer = new FileWriter(csvFile, true)) { writer.append(newLine); } return; } // 达到限制,滚动删除最旧的一条数据 File tempFile = new File("temp_" + FILE_PATH); try (BufferedReader reader = new BufferedReader(new FileReader(csvFile)); FileWriter tempWriter = new FileWriter(tempFile)) { // 写入表头 tempWriter.append(reader.readLine()).append("\n"); // 跳过最旧的第一条数据 reader.readLine(); // 复制剩余所有旧数据 String line; while ((line = reader.readLine()) != null) { tempWriter.append(line).append("\n"); } // 追加新数据 tempWriter.append(newLine); } // 临时文件写入完成后覆盖原文件,避免写入中断损坏原文件 if (csvFile.delete()) { tempFile.renameTo(csvFile); } } // 统计文件总行数,只计数不存储内容,内存占用极低 private static int countTotalRows(File csvFile) throws IOException { int rows = 0; try (BufferedReader reader = new BufferedReader(new FileReader(csvFile))) { while (reader.readLine() != null) { rows++; } } return rows; } }
方案优势
- 内存占用极低:全程逐行读写,不需要加载全文件内容,最多只存储单行字符串,就算文件到2MB上限也不会占用过多内存
- 可靠性高:所有修改先写临时文件,完成后才覆盖原文件,就算写入过程中断也不会损坏原文件
- 兼容性强:同时支持行数和文件大小两个限制条件,可根据需求调整参数优先级
如果想要进一步优化性能,可以在程序中缓存当前行数,不需要每次写入前都遍历统计,对你每分钟写入一次的场景来说,优化前后感知差异极小。
内容的提问来源于stack exchange,提问作者SwiftLearner
相关产品推荐
相关产品推荐

