For the purpose of reading a text file line by line, without loading the entire file into memory, what is the common way to do this in Rebol?
I am doing the following, but I think (correct me if I'm wrong) that it loads the whole file into memory first:
foreach line read/lines %file.txt [ print line ]
At least with Rebol2
read/lines/direct/part %file.txt 1
should come near to what you want
but if you want all lines one line after the other, it should be like
f: open/lines/direct %test.txt
while [l: copy/part f 1] [print l]
In theory you can supersede any function, even natives. I will try to give a new 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
]
]
Probably the set :word line part and the attempt should be more elaborated in order to avoid name clashes and get meaningful errors.
Yes open
is the way to go. However like sqlab touches on the necessary /lines
& /direct
refinements are not present in Rebol 3 open
(yet).
The good news though is that you can still use open
to read in large files in Rebol 3 without these refinements...
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
So you just need to wrap this up into a buffer and process a line at a time.
Here's a crude working example I've put together:
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