我编写了一个 C++ 应用程序,可以逐行读取文件。它读取一行,进行处理,然后读取下一行。
我想添加对 gzip 压缩文件的支持,并且正在寻找使用 C++ 解压缩库的替代方法。一种解决方案是解压缩整个文件,然后照常读取。
zcat
但是,我正在处理非常大的文件,并且我更喜欢通过立即解压缩文件的第一行来提供快速启动时间。问题是,如果不加以控制,zcat
解压缩文件的速度会太快,以至于我的应用程序无法跟上,并且系统命令的输出缓冲区将很快填满解压缩的 10GB 文件,而我的应用程序仍在处理前几行。
是否可以暂停zcat
,或者告诉它一次只读取一行,仅在用户指示时前进?
答案1
下面引用自手册页管道(7)。
管道容量
管道的容量是有限的。如果管道已满,则 write(2) 将阻塞或失败,具体取决于是否设置了 O_NONBLOCK 标志(见下文)。不同的实现对管道容量有不同的限制。应用程序不应依赖于特定的容量:应用程序的设计应使读取过程在数据可用时立即使用数据,以便写入过程不会保持阻塞状态。
在2.6.11之前的Linux版本中,管道的容量与系统页面大小相同(例如,i386上为4096字节)。从Linux 2.6.11开始,管道容量为65536字节。
该管道具有特定的容量,对于现代 Linux 内核来说可能是 64k。如果达到该容量,则任何写入都会被阻止,直到读取调用后有可用空间为止。因此,一般来说,zcat your_file.gz | your_program
在任何给定时间只有 64k 未压缩,因此您不必担心内存使用情况。
答案2
如果您的应用程序仅设置为读取文件而不读取文件stdin
,则可以使用进程替换。它的功能与管道类似,但 shell 会将其作为文件呈现给您的应用程序。大多数现代 shell 都提供此功能,但 POSIX 不提供此功能。这是一个例子:
yourscript <(zcat filename)
答案3
您可以使用光伏发电对传输到 zcat 的数据进行速率限制。
pv -L 5k -q < test.gz | zcat