这是我到目前为止。这不是你需要的吗?我不断收到错误“错误:未绑定模块标准”如何从OCaml中的文本文件读取行?
let r file =
let chan = open_in file in
Std.input_list (chan)
这是我到目前为止。这不是你需要的吗?我不断收到错误“错误:未绑定模块标准”如何从OCaml中的文本文件读取行?
let r file =
let chan = open_in file in
Std.input_list (chan)
如果您没有安装Extlib(显然你不基于上述错误信息)做的话,一般它的完成是这样的:
let read_file filename =
let lines = ref [] in
let chan = open_in filename in
try
while true; do
lines := input_line chan :: !lines
done; !lines
with End_of_file ->
close_in chan;
List.rev !lines ;;
如果你确实有EXTLIB:
let read_file filename =
let chan = open_in filename in
Std.input_list chan
...这是相当多的,你有什么。
如果你有Batteries-included库,你可以读入文件到Enum.t和迭代,如下所示:
let filelines = File.lines_of filename in
Enum.iter (fun line -> (*Do something with line here*)) filelines
Std.input_list
显然需要Extlib,你应该安装系统(libextlib-ocaml
和libextlib-ocaml-dev
上在Debian系统上)。
下面是使用scanf函数的递归解决方案:
let read_all_lines file_name =
let in_channel = open_in file_name in
let rec read_recursive lines =
try
Scanf.fscanf in_channel "%[^\r\n]\n" (fun x -> read_recursive (x :: lines))
with
End_of_file ->
lines in
let lines = read_recursive [] in
let _ = close_in_noerr in_channel in
List.rev (lines);;
用法:
let all_lines = read_all_lines "input.txt";;
不过,我宁愿流线由行:
let make_reader file_name =
let in_channel = open_in file_name in
let closed = ref false in
let read_next_line = fun() ->
if !closed then
None
else
try
Some (Scanf.fscanf in_channel "%[^\r\n]\n" (fun x -> x))
with
End_of_file ->
let _ = close_in_noerr in_channel in
let _ = closed := true in
None in
read_next_line;;
用法:
let read_next = make_reader "input.txt";;
let next_line = read_next();;
而且可能有点结冰:
type reader = {read_next : unit -> string option};;
let make_reader file_name =
let in_channel = open_in file_name in
let closed = ref false in
let read_next_line = fun() ->
if !closed then
None
else
try
Some (Scanf.fscanf in_channel "%[^\r\n]\n" (fun x -> x))
with
End_of_file ->
let _ = close_in_noerr in_channel in
let _ = closed := true in
None in
{read_next = read_next_line};;
用法:
let r = make_reader "input.txt";;
let next_line = r.read_next();;
希望这有助于!
[http://caml.inria.fr/pub/docs/manual-ocaml/libref/Scanf.html#space](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Scanf .html#space) _ ** ...类似地,格式字符串中的换行符匹配单个换行或回车后跟换行** _ 因此,此解决方案“应该”适用于“\ r \ n”和“\ n”样式行结尾(仅在Linux系统上测试)。 – 2012-11-10 14:22:31
所有代码片段都不关闭输入通道,因此泄漏文件描述符 – ygrek 2012-11-21 16:09:50
@ygrek:谢谢!固定。可能最好让主叫方开启/关闭业务,并让这些功能代替输入频道。 – 2012-11-21 16:47:45
使用Scanf“字符串指示”和零宽度字符从文件中读取行的另一种样式。这就像传统的祈祷风格。
open Scanf
open Printf
(* little helper functions *)
let id x = x
let const x = fun _ -> x
let read_line file = fscanf file "%[email protected]\n" id
let is_eof file = try fscanf file "%0c" (const false) with End_of_file -> true
let _ =
let file = open_in "/path/to/file" in
while not (is_eof file) do
let s = read_line file in
(* do something with s *)
printf "%s\n" s
done;
close_in file
注:
如果您已经安装了OCaml的核心库,那么很简单:
open Core.Std
let r file = In_channel.read_lines file
如果您已经安装corebuild
,那么你可以用它编译代码:
corebuild filename.byte
如果您的代码驻留在名为filename.ml
的文件中。
如果您没有OCaml Core,或者不想安装它或其他标准库实现,那么您当然可以使用vanilla OCaml的标准库来实现它。在Pervasives
模块中定义了一个函数input_line
,该函数在所有OCaml程序中自动打开(即,所有的定义都可以在没有进一步说明的情况下使用模块名称进行访问)。该函数接受in_channel
类型的值并返回从通道读取的一行。使用此功能,可以实现所需的功能:
let read_lines name : string list =
let ic = open_in name in
let try_read() =
try Some (input_line ic) with End_of_file -> None in
let rec loop acc = match try_read() with
| Some s -> loop (s :: acc)
| None -> close_in ic; List.rev acc in
loop []
此实现使用递归,并且更加自然的OCaml节目。
这读取文件的线,并打印它们:
open Core.Std
let handle_line line =
printf "Your line: %s \n" line
let() =
let file_to_read = "./file_to_read.txt" in
let lines = In_channel.read_lines file_to_read in
List.iter ~f: handle_line lines
这里是不累积的线条或使用外部库,一个简单的递归的解决方案,但可让您阅读使用有一条线,工艺函数,递归地读取下一个,直到完成,然后干净地退出。 exit函数关闭打开的文件句柄,并向调用程序发出成功信号。
let read_lines file process =
let in_ch = open_in file in
let rec read_line() =
let line = try input_line in_ch with End_of_file -> exit 0
in (* process line in this block, then read the next line *)
process line;
read_line();
in read_line();;
read_lines some_file print_endline;;
非常感谢! – Travis 2011-04-25 20:12:05
在extlib变体中检测到fd泄漏:输入通道未关闭 – ygrek 2012-11-21 16:08:27
您能解释为什么您将while循环链接为空列表?我认为它永远不会达成。 – Rizo 2015-05-08 16:32:31