我基本上试图将一个大文件(大约10G)读入一个行列表。该文件包含一个整数序列,如下所示:
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服务器,因此内存空间应该没问题)。但在搜索文档here之后,我仍然不明白OCaml
是否提供了这样的便利。
所以这是我的问题:
根据我的情况,如何快速将文件读入字符串列表?
如何使用stream
?但我需要调整相关的应用程序代码,这可能会导致一段时间。
答案 0 :(得分:7)
首先,您应该考虑是否确实需要在记忆中同时获取所有信息。也许最好逐行处理文件?
如果你真的想在内存中同时拥有它,那么你可以使用Bigarray
的{{3}}函数将文件映射为一个字符数组。然后用它做点什么。
此外,正如我所见,此文件包含数字。也许最好是按顺序分配数组(或者更好的是一个bigarray)和每个行的进程,并在(大)数组中存储整数。
答案 1 :(得分:2)
我经常使用以下两个函数来读取文件的行。请注意,函数lines_from_files
是尾递归的。
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")
答案 2 :(得分:0)
这应该有效:
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 | _ -> []
这个解决方案在读入时将字符串转换为整数(这应该是更高的内存效率,我认为这最终会对它们进行。
另外,因为它是递归的,所以必须在函数调用之外打开文件。