将大文件读入字符串行 OCaml
Read a large file into string lines OCaml
我基本上是在尝试将一个大文件(大约 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的服务器,所以内存应该没问题space)。但是我在搜索文档here.
后仍然不明白OCaml
是否提供了这样的便利
所以这是我的问题:
根据我的情况,如何快速将文件读入字符串列表?
使用stream
怎么样?但是我需要调整相关的应用程序代码,这可能会花费一些时间。
首先你应该考虑你是否真的需要在你的记忆中一次拥有所有的信息。也许逐行处理文件更好?
如果你真的想一次把它全部放在内存中,那么你可以使用Bigarray
的map_file
函数将一个文件映射为一个字符数组。然后用它做点什么。
此外,据我所知,此文件包含数字。也许最好分配数组(或者更好的是 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 | _ -> []
此解决方案在读入字符串时将其转换为整数(这应该会提高内存效率,我认为这最终将对它们完成。
此外,因为它是递归的,所以必须在函数调用之外打开文件。
我经常使用以下两个函数来读取文件的行。请注意,函数 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")
我基本上是在尝试将一个大文件(大约 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的服务器,所以内存应该没问题space)。但是我在搜索文档here.
后仍然不明白OCaml
是否提供了这样的便利
所以这是我的问题:
根据我的情况,如何快速将文件读入字符串列表?
使用
stream
怎么样?但是我需要调整相关的应用程序代码,这可能会花费一些时间。
首先你应该考虑你是否真的需要在你的记忆中一次拥有所有的信息。也许逐行处理文件更好?
如果你真的想一次把它全部放在内存中,那么你可以使用Bigarray
的map_file
函数将一个文件映射为一个字符数组。然后用它做点什么。
此外,据我所知,此文件包含数字。也许最好分配数组(或者更好的是 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 | _ -> []
此解决方案在读入字符串时将其转换为整数(这应该会提高内存效率,我认为这最终将对它们完成。
此外,因为它是递归的,所以必须在函数调用之外打开文件。
我经常使用以下两个函数来读取文件的行。请注意,函数 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")