八块腹肌的小蝌蚪 · c++ return {} - CSDN文库· 7 月前 · |
小眼睛的刺猬 · 如何使用VBA在IE中勾选复选框?· 9 月前 · |
低调的爆米花 · Sass 颜色函数 | 菜鸟教程· 1 年前 · |
英俊的卡布奇诺 · JavaScript ...· 1 年前 · |
小胡子的煎饼果子 · CComSafeArray 类 | ...· 1 年前 · |
首先,我逐行遍历文件,然后在数组中跟踪特定的行号,稍后需要引用这些数字。
该文件非常大(例如1GB或更多),因此我扫描它并将特定的行号加载到数组中,该文件不再在内存中。
在文件中读取特定行的最快和最有效的方法是什么?
该文件包含字符串文本的换行符,其中每一行代表一个事务。
与行号不同,以某种方式存储字节偏移量是否更有意义?
发布于 2022-03-12 03:06:33
当您知道行号时,从一个非常大的文件中读取一行的最快方法是什么?
以下假设文件太大,无法作为数据结构或内存映射保存在内存中。
如果您只知道行号和
,您只读取一行
,那么最快(简单)的方法是使用
BufferedReader.read
读取并计数行分隔符。
如果您要对每个文件执行多次操作,那么更复杂的是高效地执行此操作。首先,您需要一个数据结构来映射行号到文件偏移量。这必须通过读取文件、计数行和记录字节偏移量来创建。有多种表示方法,但是一组偏移量将是内存效率最高的.如果你只打算用它把一个行号映射到一个字节偏移量的话,速度最快。
不幸的是,使用
Reader
,您无法从当前字节偏移量中获取当前字节偏移量,也无法“查找”特定字节或字符偏移量的
Reader
。
因此,要实现高效的行--没有->字节偏移量的->行--文本检索,您需要使用
BufferedInputStream
或类似的。但是,您还需要让代码知道正在读取的文件的字符集:
new String(byte[], ..., Charset)
和/或
Charset
或
CharsetDecoder
API将组成一行的字节转换为
String
对象。
read(byte[], ...)
或
ByteBuffer
来提高效率,则需要小心不要在转换为字符串时破坏跨越缓冲区边界的多字节字符。
0x15
作为NL的代码)和UTF-16编码(其中CR和NL表示为2个字节而不是一个字节)。
这可不是小事..。
第二个问题是,每次应用程序用给定的行号读取行时,它首先需要“查找”流到正确的字节偏移量。根据访问模式的不同,这可能需要
seek
系统调用,然后是
read
系统调用。根据访问模式的不同,最好实现某种类型的缓存。你可以把你读到的那一行.或者,您可以在磁盘块边界和缓存前面和/或以下行进行读取。最佳策略将取决于访问模式等,而且可能只能通过实验确定。
(在数据库中存储行可能更简单和/或更有效,而不是从1GB+文本文件中读取。数据库通常会为您执行一些服务器端缓存,并且实现客户端缓存的方法多种多样。)
发布于 2022-03-14 23:23:07
这个问题有点不清楚,所以我将提出多种可能性,并对每种可能性提出解决方案。
我跟踪特定的线路号码,我需要以后参考。
您知道在开始之前需要检索的所有行吗?或者有某种机制来识别这些线?
如果是,那么最简单的解决方案是使用
BufferedReader.readLine()
读取文件一次。将检索到的每一行存储在
Map
中,并按其行号进行键控。
该文件非常大(例如,1GB或更多)
在这个大小下,我实际上将整个文件读入
Map
-- 1GB没有那么大。我可能会使用
TreeMap
,因为它的内部结构比
HashMap
稍小,而且性能上的差别并不明显。
与行号不同,以某种方式存储字节偏移量是否更有意义?
是的,事实上这就是你必须做的。事实上,我会存储每一行的开始和结束偏移量,但是您可以只存储开始--结束是下一行的开始- 1。
在
long[]
中存储将是最有效的,因为
ArrayList<Long>
会为每个条目设置对象开销。但是,对于前者,您必须分配一个大于可能行数的数组,并且/或自行处理调整大小的操作。
您需要读取整个文件才能确定行分隔符。但是,只要文件使用标准的
\n
(或
\r
)行分隔符,并且使用与uses兼容的编码(例如,iso-8859-x、utf-8,甚至utf-16/utf-32,只要注意读取大小),那么在读取文件时不需要进行任何字符集翻译。
我会使用
BufferedInputStream
,一次读一个字符。这意味着从数组中检索单个字节,因此至少要尽可能快地完成--至少使用
java.io
。
如果您的文件小于2GB,则可以使用
MappedByteBuffer
。这将在一次读取一个字节时稍微提高性能,因为它不需要将字节从OS缓冲区复制到Java堆上。它还利用操作系统读取和缓存页面,这可能导致更高效的读取(例如,因为操作系统决定一次读取多个块)。
要读取行,需要查找起始偏移量,获取其与结束偏移量之间的字节,然后调用
new String(b, charset)
。
如果您不使用
MappedByteBuffer
,那么我建议使用
FileChannel
而不是
RandomAccessFile
。这也将利用页面缓存(尽管程度较小),并且不需要对每次读取都使用syscall。
发布于 2022-03-12 02:33:10
您可以使用BufferedReader从文件中读取,它比其他方式更可靠。如果我简单地说,如果您要求使用BufferedReader读取一行--它一次读取多行,但它给了您要查找的行--其余的行存储在缓冲区中,当您再次请求另一行时,它将检查缓冲区中是否存在行--它将从缓冲区中给出该行,它不会每次都进入已保存的内存从文件中读取。
https://stackoverflow.com/questions/71446467
复制相似问题
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2023 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号: 粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
八块腹肌的小蝌蚪 · c++ return {} - CSDN文库 7 月前 |
小眼睛的刺猬 · 如何使用VBA在IE中勾选复选框? 9 月前 |
低调的爆米花 · Sass 颜色函数 | 菜鸟教程 1 年前 |