生成一个 10 行的文本文件,每一行以 "\n" 结尾,统计行数为 10 。
def generate_file():
with open("line.log", "w") as f:
for i in range(1, 10+1):
f.write(f"Line is: your target line{i} to print\n")
def chunked_file_reader(fp, block_size=4 * 1024):
while True:
chunk = fp.read(block_size)
if not chunk:
break
yield chunk
def get_line_count(fname):
count = 0
with open(fname) as fp:
for chunk in chunked_file_reader(fp):
count += chunk.count("\n")
return count
generate_file()
line_count = get_line_count("line.log")
# > 10
block_size 亦或者说 buffering 传入的大小是每一行的长度,count 结果会变成 9 ,求解
def return_count(fname):
count = 0
with open(fname) as fp:
line = fp.readline()
for chunk in chunked_file_reader(fp, len(line)):
count += chunk.count("\n")
return count
generate_file()
line_count = get_line_count("line.log")
# > 9
1
NoOneNoBody 2023-08-03 15:38:22 +08:00
最后一行没有\n 的,是 EOF
|
2
evemoo OP @NoOneNoBody
如果我去掉 line = fp.readline() 这行直接传 36 (每一行的长度),返回值也是 10 如果加上这一行打印每一个 chunk ,则是从第二行开始了:Line is: your target line2 to print 所以我的疑惑是:open 里面的函数 read 、readline 、readlines 会影响后续的 chunk 读取? |
3
yushenglin 2023-08-03 16:05:46 +08:00 1
你用 readline()操作得到时候,文件流已经操作到第一行后面了,你后面就只能读到 9 个,你可以试下用下 fp.seek(0),恢复到文件开始位置,又会变成 10 个了
|
4
NoOneNoBody 2023-08-03 16:07:59 +08:00 1
@evemoo #2
呃,我看漏了,前面说的不对 readline 是读取一行,完成时指针已经跳到第二行,所以统计少了一个\n 所以 line = fp.readline() 是没必要的,还造成后面的 for 读少了一行,包括行数和首行内容 如果有其他需求非要读取首行,那需要一个把指针复位到文件开始的操作,或者按这样写但最后合并处理(计数器要补加 1 ) |
5
evemoo OP @yushenglin 确实是这样
如果要分页读取数据,比如 10 行总计 400 bytes ,假设分 5 页,每页两行、每页 80 bytes 。 fp.seek() 该怎么读取指定页面指定行呢?比如我想读取第三页的第二行 |
6
yushenglin 2023-08-03 16:56:35 +08:00
@evemoo 这种只能通过计算去处理了,暂时没想到什么好办法,可以期待一下其他大牛的回复
|
7
westoy 2023-08-03 17:04:39 +08:00 1
文本数据要效率的话, 最少要维护一个 offset_t[]的索引文件的
直接用 sqlite 吧, 别折腾了 |
8
marcolin18 2023-08-03 17:47:34 +08:00
@westoy 同意 sqlite ,或者 OP 说说场景
|
9
evemoo OP @marcolin18 没有什么场景,就是最近遇到大文件读写指定行的时候发散思维到分页处理上。
后续会试试 sqlite 的,先谢谢上面各位了。 |