这是我到目前为止所拥有的。这不就是你需要的吗?我一直收到错误“错误:未绑定的模块标准”
let r file =
let chan = open_in file in
Std.input_list (chan)
答案 0 :(得分:22)
如果您没有安装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
答案 1 :(得分:16)
如果您安装了OCaml Core库,那么它就像:
一样简单open Core.Std
let r file = In_channel.read_lines file
如果您安装了corebuild
,那么您可以使用它编译代码:
corebuild filename.byte
如果您的代码位于名为filename.ml
的文件中。
如果您没有OCaml Core,或者不想安装它,或者其他一些标准库实现,那么,当然,您可以使用vanilla OCaml的标准库来实现它。在input_line
模块中定义了一个函数Pervasives
,它在所有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编程更自然。
答案 2 :(得分:1)
这是使用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 ();;
希望这有帮助!
答案 3 :(得分:1)
使用Scanf&#34;字符串指示&#34;从文件中读取行的另一种样式和零宽度字符。这就像传统的命令式风格。
open Scanf
open Printf
(* little helper functions *)
let id x = x
let const x = fun _ -> x
let read_line file = fscanf file "%s@\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
注:
答案 4 :(得分:1)
这将读取文件的行并打印每一行:
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
答案 5 :(得分:0)
Std.input_list
显然需要Extlib,您应该在系统上安装libextlib-ocaml
和libextlib-ocaml-dev
在Debian系统上。
答案 6 :(得分:0)
这是一个简单的递归解决方案,它不会累积行或使用外部库,但是让您读取一行,使用函数处理它,递归读取下一个直到完成,然后干净地退出。 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;;
答案 7 :(得分:0)
这只是将整个文件加载到一个大字符串中,但您可以随时将其拆分为一个列表。
let read_file path =
let channel = open_in path in
let buffer = Buffer.create 1024 in
let rec go () =
try
Buffer.add_channel buffer channel 1024; go ()
with End_of_file ->
Buffer.contents buffer in
go ();;