将大文件读入字符串行OCaml
我基本上是想把一个大文件(大约10G)读入一个行列表。该文件包含一个整数序列,如下所示:将大文件读入字符串行OCaml,ocaml,filereader,Ocaml,Filereader,我基本上是想把一个大文件(大约10G)读入一个行列表。该文件包含一个整数序列,如下所示: 0x123456 0x123123 0x123123 ..... 默认情况下,我使用下面的方法读取代码库中的文件,但在这种情况下,退出速度很慢(约12分钟) let lines_from_file (filename : string) : string list =
0x123456
0x123123
0x123123
.....
默认情况下,我使用下面的方法读取代码库中的文件,但在这种情况下,退出速度很慢(约12分钟)
let lines_from_file (filename : string) : string list =
let lines = ref [] in
let chan = open_in filename in
try
while true; do
lines := input_line chan :: !lines
done; []
with End_of_file ->
close_in chan;
List.rev !lines;;
我想我需要将文件读入内存,然后将它们分成几行(我使用的是128G服务器,所以它应该适合内存空间)。但是在搜索文档后,我仍然不知道OCaml
是否提供了这样的功能
所以我的问题是:
流
怎么样?但我需要调整相关的应用程序代码,这可能会导致一些时间首先,你应该考虑你是否真的需要在你的记忆中同时拥有所有的信息。也许逐行处理文件更好 如果您真的想在内存中同时保存所有文件,那么可以使用
Bigarray
的函数将文件映射为字符数组。然后用它做点什么
而且,正如我看到的,这个文件包含数字。也许最好是分配数组(或者更好的是bigarray)并按顺序处理每一行,并在(大)数组中存储整数 这应该有效:
let rec ints_from_file fdesc =
try
let l = input_line fdesc in
let l' = int_of_string l in
l' :: ints_from_file fdesc
with | _ -> []
这个解决方案在读取字符串时将其转换为整数(这应该会更节省内存,我认为最终会对它们执行此操作)
此外,由于它是递归的,因此必须在函数调用之外打开文件。我经常使用以下两个函数来读取文件的行。请注意,函数
文件中的行是尾部递归的
let read_line i = try Some (input_line i) with End_of_file -> None
let lines_from_files filename =
let rec lines_from_files_aux i acc = match (read_line i) with
| None -> List.rev acc
| Some s -> lines_from_files_aux i (s :: acc) in
lines_from_files_aux (open_in filename) []
let () =
lines_from_files "foo"
|> List.iter (Printf.printf "lines = %s\n")
为什么不将这些行打印到一个新文件中呢?以相反的顺序,一次打印一行。ocaml中的流是什么情况?Stdlib的流是否被视为已弃用?是的,它处于边缘。它实际上在ocaml的第一个版本中已弃用,因为它是Caml Light的一种返祖现象。否则,流就可以了。您可以使用Lwt\sStream
、Async的管道、Core的序列
或Batters的枚举
来创建字符/字符串的序列或流。但这些都只是Core库中的不太通用的版本。折叠核心库的行
。如果它基本上已被弃用,那么为什么不只是从标准库中删除。流的弃用是。嗨@ivg,请问您对“逐行处理文件”有何建议?使用流
?该函数不是尾部递归函数,因此在大文件上会产生堆栈溢出。使用累加器,然后以列表结束。rev
更为可取。即使使用累加器,由于try/with
节,堆栈仍会随着文件大小线性增长。@alifirat他的解决方案非常地道。