在 stdin 上使用 really_input_string 进行非法查找
Illegal Seek with really_input_string on stdin
我正在改造一些代码以接受来自 stdin 的输入(除了文件)。
print_string (really_input_string stdin (in_channel_length stdin))
这在我重定向标准输入时有效:-
$ ./a.out < /tmp/lorem.txt
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
但是没有等待我的输入就失败了:-
$ ./a.out
Fatal error: exception Sys_error("Illegal seek")
$
或者:-
$ cat /tmp/lorem.txt | ./a.out
Fatal error: exception Sys_error("Illegal seek")
如何让后者也起作用?
你没有提到你使用的是什么系统。
Unix 查找操作仅对常规文件有意义,即存储在磁盘(或类似的随机可寻址媒体)上的文件。在通常的 Unix 实现中,终端设备或管道上的查找会被忽略。但是,在您使用的系统中,这些似乎被视为错误。这让我怀疑您没有使用类 Unix(或足够类 Unix)的系统。
无论如何,问题似乎是 in_channel_length
寻找文件的末尾以确定它有多大。在您的系统中,当输入来自终端或管道时,这不起作用。
当输入来自管道或终端时,即使在 Unix 系统上,也很难看出代码如何按预期工作。
我建议您编写自己的循环来读取直到看到 EOF。
这是一个粗略的实现,可能足以用于文本文件:
let my_really_read_string in_chan =
let res = Buffer.create 1024 in
let rec loop () =
match input_line in_chan with
| line ->
Buffer.add_string res line;
Buffer.add_string res "\n";
loop ()
| exception End_of_file -> Buffer.contents res
in
loop ()
我正在改造一些代码以接受来自 stdin 的输入(除了文件)。
print_string (really_input_string stdin (in_channel_length stdin))
这在我重定向标准输入时有效:-
$ ./a.out < /tmp/lorem.txt
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
但是没有等待我的输入就失败了:-
$ ./a.out
Fatal error: exception Sys_error("Illegal seek")
$
或者:-
$ cat /tmp/lorem.txt | ./a.out
Fatal error: exception Sys_error("Illegal seek")
如何让后者也起作用?
你没有提到你使用的是什么系统。
Unix 查找操作仅对常规文件有意义,即存储在磁盘(或类似的随机可寻址媒体)上的文件。在通常的 Unix 实现中,终端设备或管道上的查找会被忽略。但是,在您使用的系统中,这些似乎被视为错误。这让我怀疑您没有使用类 Unix(或足够类 Unix)的系统。
无论如何,问题似乎是 in_channel_length
寻找文件的末尾以确定它有多大。在您的系统中,当输入来自终端或管道时,这不起作用。
当输入来自管道或终端时,即使在 Unix 系统上,也很难看出代码如何按预期工作。
我建议您编写自己的循环来读取直到看到 EOF。
这是一个粗略的实现,可能足以用于文本文件:
let my_really_read_string in_chan =
let res = Buffer.create 1024 in
let rec loop () =
match input_line in_chan with
| line ->
Buffer.add_string res line;
Buffer.add_string res "\n";
loop ()
| exception End_of_file -> Buffer.contents res
in
loop ()