将大文件读入字符串行OCaml

将大文件读入字符串行OCaml,ocaml,filereader,Ocaml,Filereader,我基本上是想把一个大文件(大约10G)读入一个行列表。该文件包含一个整数序列,如下所示: 0x123456 0x123123 0x123123 ..... 默认情况下,我使用下面的方法读取代码库中的文件,但在这种情况下,退出速度很慢(约12分钟) let lines_from_file (filename : string) : string list =

我基本上是想把一个大文件(大约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服务器,所以它应该适合内存空间)。但是在搜索文档后,我仍然不知道
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他的解决方案非常地道。