文件操作
本指南介绍如何在 OCaml 中使用标准库执行基本文件操作。
相关模块的官方文档:包括初始打开的 Stdlib 和 Printf 模块的内核库。
缓冲通道
在 OCaml 中,打开文件的正常方式返回一个 **通道**。通道有两种类型:
- 写入文件的通道:类型
out_channel
- 从文件读取的通道:类型
in_channel
写入
要写入文件,您需要执行以下操作:
- 打开文件以获取
out_channel
- 写入通道
- 如果您想强制写入物理设备,则必须刷新通道,否则写入不会立即发生。
- 完成后,您可以关闭通道。这将自动刷新通道。
常用函数:open_out
、open_out_bin
、flush
、close_out
、close_out_noerr
标准 out_channel
:stdout
、stderr
读取
要从文件读取数据,您需要执行以下操作:
- 打开文件以获取
in_channel
- 从通道读取字符。读取会消耗通道,因此如果您读取一个字符,通道将指向文件中的下一个字符。
- 当没有更多字符可读时,将引发
End_of_file
异常。通常,这就是您想要关闭通道的地方。
常用函数:open_in
、open_in_bin
、close_in
、close_in_noerr
标准 in_channel
:stdin
查找
每当您向通道写入或从通道读取内容时,当前位置都会更改为刚刚写入或读取内容的下一个字符之后。有时,您可能想要跳过文件中的特定位置,或从开头重新开始读取。对于指向普通文件的通道,可以使用 seek_in
或 seek_out
来实现这一点。
注意事项
- 如果您想要实际写入内容,请不要忘记刷新您的
out_channel
。这在您写入非文件(例如标准输出 (stdout
) 或套接字)时尤其重要。 - 不要忘记关闭任何未使用的通道,因为操作系统对可以同时打开的文件数量有限制。您必须捕获文件操作期间发生的任何异常,关闭相应的通道,并重新引发异常。
Unix
模块提供对非缓冲文件描述符(以及其他内容)的访问。它提供与相应的标准通道具有相同名称的标准文件描述符:stdin
、stdout
和stderr
。因此,如果您执行open Unix
,您可能会遇到类型错误。如果您想确保您使用的是stdout
通道而不是stdout
文件描述符,可以在其来源模块名称之前加上它:Stdlib.stdout
。请注意,大多数似乎不属于任何模块的内容实际上都属于Stdlib
模块,该模块会自动打开。open_out
和open_out_bin
会截断给定文件(如果它已经存在)!如果您想要其他行为,请使用open_out_gen
。
示例
let file = "example.dat"
let message = "Hello!"
let () =
(* Write message to file *)
let oc = open_out file in
(* create or truncate file, return channel *)
Printf.fprintf oc "%s\n" message;
(* write something *)
close_out oc;
(* flush and close the channel *)
(* Read file and display the first line *)
let ic = open_in file in
try
let line = input_line ic in
(* read line, discard \n *)
print_endline line;
(* write the result to stdout *)
flush stdout;
(* write on the underlying device now *)
close_in ic
(* close the input channel *)
with e ->
(* some unexpected exception occurs *)
close_in_noerr ic;
(* emergency closing *)
raise e
(* exit with error: files are closed but channels are not flushed *)
(* normal exit: all channels are flushed and closed *)
我们可以编译并运行此示例
$ ocamlopt -o file_manip file_manip.ml
$ ./file_manip
Hello!