我有很多行的文本文件。我想编写一个简单的 OCaml 程序,该程序将逐行处理此文件并可能打印该行。
为了编写这个程序,我首先创建了一个较小的文件,行数更少 - 这样程序将更快地完成执行。
$ wc -l input/master
214745 input/master
$ head -50 input/master > input/small-master
filter.ml
这是我编写的简单样板程序:
open Core.Std;;
open Printf;;
open Core.In_channel;;
if Array.length Sys.argv >= 2 then begin
let rec process_lines ?ix master_file =
let ix = match ix with
| None -> 0
| Some x -> x
in
match input_line master_file with
| Some line -> (
if ix > 9 then printf "%d == %s\n" ix line;
process_lines ~ix:(ix+1) master_file
)
| None -> close master_file
in
let master_file = create Sys.argv.(1) in
process_lines master_file
end
它将输入文件的位置作为命令行参数,创建用于读取此文件的文件句柄,并process_lines
使用此文件句柄作为参数调用递归函数。
process_lines
ix
当它从文件句柄逐行读取时,使用可选参数来计算行号。process_lines 只是将读取的行打印file_handle
到标准输出。
然后,当我在较小的输入文件上执行程序并将输出传送到 Linuxhead
命令时,一切正常:
$ ./filter.native input/small-master |head -2
10 == 1000032|BINCH JAMES G|4|2012-11-13|edgar/data/1000032/0001181431-12-058269.txt
11 == 1000032|BINCH JAMES G|4|2012-12-03|edgar/data/1000032/0001181431-12-061825.txt
而且,当我在较大的文件上执行程序时,我看到了一个损坏的管道错误:
$ ./filter.native input/master |head -2
10 == 1000032|BINCH JAMES G|4|2012-11-13|edgar/data/1000032/0001181431-12-058269.txt
11 == 1000032|BINCH JAMES G|4|2012-12-03|edgar/data/1000032/0001181431-12-061825.txt
Fatal error: exception Sys_error("Broken pipe")
Raised by primitive operation at file "pervasives.ml", line 264, characters 2-40
Called from file "printf.ml", line 615, characters 15-25
Called from file "find.ml", line 13, characters 21-48
Called from file "find.ml", line 19, characters 2-27
我了解到,当管道的读取器(在本例中为head
命令)在管道的编写者(在本例中为我的 OCaml 程序)完成写入之前退出时,会发生此类损坏的管道错误。这就是为什么如果我将tail
命令用作阅读器,我将永远不会收到这样的错误。
但是,当文件的行数较少时,为什么没有发生断管错误?