为了逐行读取文本文件,而不将整个文件加载到内存中,在Rebol中执行此操作的常用方法是什么?
我正在做以下事情,但我认为(纠正我,如果我错了)它首先将整个文件加载到内存中:
foreach line read/lines %file.txt [ print line ]
答案 0 :(得分:5)
至少使用Rebol2
read/lines/direct/part %file.txt 1
应该接近你想要的东西
但是如果你想要所有的行一行接一行,它应该像
f: open/lines/direct %test.txt
while [l: copy/part f 1] [print l]
理论上,你可以取代任何功能,甚至是本地人。我会尝试给出一个新的foreach
foreach_: :foreach
foreach: func [
"Evaluates a block for each value(s) in a series or a file for each line."
'word [get-word! word! block!] {Word or block of words to set each time (will be local)}
data [series! file! port!] "The series to traverse"
body [block!] "Block to evaluate each time"
/local port line
] [
either any [port? data file? data] [
attempt [
port: open/direct/lines data
while [line: copy/part port 1] [
set :word line
do :body
line
]
]
attempt [close port]
] [
foreach_ :word :data :body
]
]
可能是 set:word line 部分,并且应该更详细地尝试,以避免名称冲突并获得有意义的错误。
答案 1 :(得分:2)
是open
是要走的路。但是,像 sqlab 那样触及必要的/lines
& Rebol 3 open
(尚未)中没有/direct
个优化。
但好消息是,如果没有这些改进,你仍然可以在Rebol 3中使用open
to read in large files ......
file: open %movie.mpg
while [not empty? data: read/part file 32000] [
;
; read in 32000 bytes from file at a time
; process data
]
close file
因此,您只需将其包装到缓冲区中并一次处理一行。
这是一个粗略的工作示例,我把它放在一起:
file: open/read %file.txt
eol: newline
buffer-size: 1000
buffer: ""
lines: []
while [
;; start buffering
if empty? lines [
;; fill buffer until we have eol or EOF
until [
append buffer to-string data: read/part file buffer-size
any [
empty? data
find buffer eol
]
]
lines: split buffer eol
buffer: take/last lines
]
line: take lines
not all [empty? data empty? buffer]
][
;; line processing goes here!
print line
]
close file