如何控制Scanf.Scanning的缓冲区?
问题描述:
的Scanf
模块似乎表现得稍微 违反直觉的,因为它不尊重 底层信道的状态:如果该通道被重建如何控制Scanf.Scanning的缓冲区?
(* prepare test data *)
let() =
let oc = open_out "test.txt" in
output_string oc "abcdefghij\n";
close_out oc
;;
let ic = open_in "test.txt"
(* ic at offset 0: “ab…” *)
let() =
let sc = Scanf.Scanning.from_channel ic in
let s = Scanf.bscanf sc "%2s" (fun s -> s) in
Printf.eprintf "read [%s]\n" s (* -> [ab] *)
;; (* sc out of scope at this point *)
(* hint: close ic here and reopen for expected result *)
seek_in ic 4
(* ic at offset 4: “ef…” *)
let() =
let sc = Scanf.Scanning.from_channel ic in
let s = Scanf.bscanf sc "%2s" (fun s -> s) in
Printf.eprintf "read [%s]\n" s (* -> [cd] ‽ *)
;;
close_in ic
显然的Scanning.t
内部缓冲器生存它 。有另一种方法来强制重新同步 ?该docs 声称“读书开始于IC的当前阅读位置。”
我会很感激在什么地方正是这种行为 记录。
答
就一般的设计原则而言,我会说对Scanf.Scanning.from_channel
的呼叫将通道的责任移动到Scanf
模块。如果您在Scanf
模块的背后并直接操作频道(如您在seek_in
中所做的那样),则无法保证正常工作。
事情与我用过的几乎每个分层I/O库的工作类似。例如,你不能使用来自Unix stdio的fdopen()
,并希望通过FILE
抽象读取数据,同时也以任意方式操作底层文件描述符。
如果文档提到了这些问题(在这两种情况下),这可能会很好。
我正在阅读大部分二进制文件,因此大部分时间都不需要“Scanf”。 –
您可以尝试将文本读入缓冲区,然后使用'sscanf'。根据我的经验,'sscanf'比使用频道扫描更容易使用,更加可靠。几十年来我没有在生产代码中使用过scanf。如果你的文本很简单,你也可以使用'int_of_string'等。 FWIW。 –