3

我正在寻找从stdinC 编程中的管道读取数据的最佳方法。

问题:我需要寻找这些数据,即在同一流的末尾读取一些数据后,我需要从流的开头读取数据。

小用例:gunzip -c 4GbDataFile.gz | myprogram

另一个 :

  1. 在本地主机上:nc -l -p 1234 | myprogram
  2. 在远程主机上:gunzip -c 4GbDataFile.gz | nc -q 0 theotherhost 1234

我知道从 fifo 读取只能完成一次。所以,目前:

  • 把所有东西都stdin 内存中吸了出来,并从这个分配的内存中工作。

这很丑陋,但它有效。一个明显的问题是,如果有人向我的应用程序发送一个巨大的(或连续的)流,我将以分配的大内存块结束,否则我将耗尽内存。(考虑一个 8Gb 的文件)

我接下来的想法:

  • 我设置了该内存块的大小限制(可能是用户定义的)。一旦我从 stdin 读取了这么多数据:
    1. 要么我停在这里:“错误。内存不足,bazinga。算了吧。” 风格。
    2. 要么我开始将正在读取的内容转储到文件中,并在读取所有数据后从该文件中工作。

但是,这有什么意义呢?我无法找出我正在阅读的数据的来源。如果这是一个本地 8Gb 文件,我会将其转储到同一系统上的另一个 8Gb 文件中。

所以,我的问题是:

当您必须在管道中来回查找时,如何有效地从管道中读取大量数据?stdin

提前感谢您的回答。

编辑 :

我的程序需要在给定文件的某处(取决于文件格式)读取元数据,因此可能在流的末尾。然后它可能会在流的开头读回其他数据,然后在另一个地方等。简而言之:它需要访问数据的任何字节。

一个例子是在开始读取之前在不知道文件格式的情况下读取存档文件的数据stdin:我需要检查存档元数据,查找存档文件名称和偏移量等。

因此,我将制作标准输入内容的本地副本并从中工作。感谢大家的投入;)

4

3 回答 3

1

你需要明确你的要求。如果您需要seek()那么显然您不能从stdin获取输入。如果你需要seek()那么你应该把输入文件名作为参数。

于 2012-05-07T11:27:12.393 回答
0

4GbDataFile 中的数据结构不适合您想做的事情。创造性思考。不要把你的程序锤成它甚至不应该尝试的东西。尝试修复生成它的输入格式,这样您就不需要回溯 4 GB。

如果您喜欢锤击:4GB 的核心内存非常昂贵。相反,将从标准输入读取的数据保存在一个文件中,然后打开该文件(或映射它)并寻找您心中的内容。

于 2012-05-07T11:35:15.833 回答
0

我认为您应该阅读臭名昭著的无用猫奖

TL;DR:更改cat 4gbfile | yourprogramyourprogram < 4gbfile.

如果你真的坚持让它处理来自管道的数据,你必须在启动时将它存储在一个临时文件中,然后用临时文件的 fd 副本替换文件描述符 0,使用dup2.

于 2012-05-07T12:11:44.260 回答