将大文件读入字符串行OCaml

时间:2015-08-18 16:06:48

标签: ocaml filereader

我基本上试图将一个大文件(大约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是否提供了这样的便利。

所以这是我的问题:

  1. 根据我的情况,如何快速将文件读入字符串列表?

  2. 如何使用stream?但我需要调整相关的应用程序代码,这可能会导致一段时间。

3 个答案:

答案 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 | _ -> []

这个解决方案在读入时将字符串转换为整数(这应该是更高的内存效率,我认为这最终会对它们进行。

另外,因为它是递归的,所以必须在函数调用之外打开文件。