我有一个超过200.000行的大文本文件,我需要阅读几行。例如:第10.000至20.000行。
重要提示:由于性能问题,我不想打开并搜索完整文件以提取这些行。
这可能吗?
答案 0 :(得分:6)
如果行是固定长度的话,那么就可以寻找特定的字节位置并加载你想要的行。如果行是可变长度,找到您要查找的行的唯一方法是解析文件并计算行尾标记的数量。如果文件不经常更改,您可以通过执行一次解析然后保留每行的字节位置索引来加速将来的访问(可能将该索引写入磁盘,因此它不需要是每次运行程序时都会完成。)
答案 1 :(得分:1)
除非你知道所有行的长度相同(在这种情况下你可以寻找offset = line_number * line_size_in_bytes,其中line_number从零开始计算,line_size_in_bytes包括所有行),你必须搜索文件来计算换行符。行中的字符。)
如果这些行是可变的/未知的长度,那么在读取它时,你可以索引每行的起始偏移量,以便随后的读取可以寻找给定行的开始。
答案 2 :(得分:0)
如果这些行的长度都相同,则可以计算给定行的偏移量,并只读取这些字节。
如果行的长度不同,那么你真的必须读取整个文件以计算有多少行。行终止字符只是文件中的任意字节。
答案 3 :(得分:0)
如果线是固定长度,那么你只需计算偏移量,没问题。
如果它们不是(即常规CSV文件),那么您需要浏览该文件,以构建索引或只读取您需要的行。要使文件读取速度更快,最好使用内存映射文件(请参阅Boost iostreams的一部分实现:http://www.boost.org/doc/libs/1_39_0/libs/iostreams/doc/classes/mapped_file.html)。
答案 4 :(得分:0)
正如其他人所指出的,如果你没有固定宽度的线条,那么在没有构建索引的情况下是不可能的。但是,如果您控制文件的格式,如果您设法存储行本身的编号,则可以在查找起始行时获得~O(日志(大小))而不是O(大小)性能每一行,即让文件内容看起来像这样:
1: val1, val2, val3
2: val4
3: val5, val6
4: val7, val8, val9, val10
使用这种格式的文件,您可以通过二进制搜索快速找到所需的行:从搜索到文件的中间开始。阅读下一个换行符。然后读取该行,并解析该数字。如果数字大于目标,则需要在文件的前半部分重复算法,如果它小于目标行号,则需要在文件的后半部分重复该算法。
你需要小心角落的情况(例如:范围的“开头”和范围的“结束”在同一条线上等),但对我来说,这种方法在过去用于解析其中包含日期的日志文件(我需要找到特定时间戳之间的行)。
当然,这仍然没有超过显式构建索引或固定大小记录的性能。