【发布时间】:2015-01-14 09:25:41
【问题描述】:
为了逐行读取文本文件,而不是将整个文件加载到内存中,Rebol 中常用的方法是什么?
我正在执行以下操作,但我认为(如果我错了,请纠正我)它首先将整个文件加载到内存中:
foreach line read/lines %file.txt [ print line ]
【问题讨论】:
标签: rebol
为了逐行读取文本文件,而不是将整个文件加载到内存中,Rebol 中常用的方法是什么?
我正在执行以下操作,但我认为(如果我错了,请纠正我)它首先将整个文件加载到内存中:
foreach line read/lines %file.txt [ print line ]
【问题讨论】:
标签: rebol
至少在 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 部分,并且尝试应该更加详细,以避免名称冲突并获得有意义的错误。
【讨论】:
open/lines/direct 不是将整个文件加载到内存中吗?根据我的问题,这就是我要避免的。
open('file.txt').each {|line| puts line}。我想人们可以在 Rebol 中编写 foreach 函数的变体来执行类似的接受文件或端口的操作。你能改变标准函数的行为吗? (例如让foreach 接受port!)?
是的open 是要走的路。然而,像 sqlab 一样,必要的 /lines 和 /direct 改进在 Rebol 3 open 中不存在(目前)。
不过好消息是,如果没有这些改进,您仍然可以在 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
【讨论】:
open('file.txt').each {|line| puts line}。我想可以在 Rebol 中编写 foreach 函数的变体来执行类似的接受文件或端口的操作。你能改变标准函数的行为吗? (例如让foreach 接受port! ?