我需要通过检查文件中的行数是否匹配(近似)附加到预告片的数字来验证相当大的分隔文件。
方法很少,我不接受:
- 在堆中放入整个文件
- 在验证步骤完成之前,处理无法启动。
到目前为止我所拥有的:
我拖尾并解析预告片以获得行数,这非常有效。
我打算做什么: 从文件中获取0.5 / 1mb的行样本(理想情况下是随机的),计算其中的行并相应地相乘,以获得整个文件中行的近似值。
我不想限制自己通过读取第一行“n”行来创建样本,然后检查其大小......
问题:
是否有可能获得这样的样本,而无需读取整个文件?我是否可以从文件中间开始获取n行,而无需重新创建原始文件的一部分(例如head '-c/n' 'x' file.csv > file1.csv
效率不高)?
答案 0 :(得分:1)
是否有可能获得这样的样本,而无需读取整个文件?
是
我可以从文件中间开始提取n行,而无需重新创建原始文件的一部分。
是
File.length()
获取文件的长度。FileInputStream
FileInputStream.skip(N)
跳到要采样的偏移量。 (我已检查过Java 8源代码,skip
效率很高。它使用lseek
系统调用而不是读取字节...)BufferedReader(InputStreamReader)
中并使用BufferedReader.readLine()
计算M行并计算其平均长度。稍微退一步,我对问题本身有几点意见:
我需要通过检查文件中的行数是否匹配(近似)附加到预告片的数字来验证相当大的分隔文件。
目前尚不清楚近似匹配是否有多大帮助。我想,这取决于你试图检测的失败模式。
您不希望大多数/所有输入文件的平均记录相同吗?如果是这样,将行数(来自预告片)与文件大小x预期的平均记录数进行验证可能更有意义。
在一小部分记录不好的情况下,采样不会发现问题。而且这种不良可能是空行或多个/大多数/所有字段为空的记录。
还有一个问题是,做一个单独的"快速"是否是一个好主意。验证一个这么大的文件。如果您发现问题,您可以做什么?重新获取它?重新发送?在处理它时,进行完整验证是不是更好?将文件缩小会不会更好?对于这样大小的文件,选择比CSV更紧凑的表示形式会不会更好?
答案 1 :(得分:0)
如果您的文件大小为50 GB,那么将整个文件放入堆中确实可能不太好。
您可以使用内存映射文件,例如,您可以读取整个文件,而无需将其完全加载到主内存中。
您可以使用RandomAccessFile和MappedByteBuffer打开 文件的一个区域作为MemoryMapped缓冲区。 看看RandomAccessFile.getChannel和FileChannel.map方法。