用于从标准输入读取的 Win32 缓冲区大小
Win32 buffer size for read from stdin
我正在尝试在 Windows 上用 C++ 高效地从标准输入读取数据,这意味着最好是大块读取。这可以通过以下方式完成:
ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, bytestoread, &bytesread, 0);
或
read(0, buf, bytestoread);
但在这两种情况下,它仅在 bytestoread
设置为非常小的数字时有效,例如50;如果设置为更大的数字,例如一兆字节,调用失败并出现 'not enough space' 错误,就好像数据没有直接进入我提供的缓冲区,而是通过一些固定大小的内部缓冲区复制。无论输入是通过管道还是在控制台上输入,都是如此。
Windows 是否仅限制进程一次可以从 stdin 读取的块大小?如果是这样,保证工作的最大块大小是多少?
显示问题的完整程序:
#include <errno.h>
#include <io.h>
#include <stdio.h>
#include <string.h>
char buf[1000000];
int main(int argc, char **argv) {
auto r = read(0, buf, sizeof buf);
if (r < 0)
perror("read");
return 0;
}
据我所知,是stdin
没有限制。它作为一个无尽的流工作,应该提供你需要的尽可能多的存储空间。我看到的唯一选择是您正在使用的内核在某些时候会阻塞
您没有说明您使用的是哪个版本的运行时和 OS,但我无法在 Windows 10 上使用 MSVC 19.16.27031.1 重现此问题。有一些记录在案的原因可能会失败。来自 MSDN documentation of ReadFile
:
Characters can be read from the console input buffer by using ReadFile
with a handle to console input. The console mode determines the exact behavior of the ReadFile
function. By default, the console mode is ENABLE_LINE_INPUT
, which indicates that ReadFile
should read until it reaches a carriage return. If you press Ctrl+C, the call succeeds, but GetLastError
returns ERROR_OPERATION_ABORTED
. For more information, see CreateFile
.
还有另一种方法可能会导致此错误,与异步有关 I/O,但这似乎不是这里的问题。您可能想用 SetConsoleMode
关闭 ENABLE_LINE_INPUT
标志。该文档还说,如果无法锁定缓冲区的内存页面,调用可能会失败并返回 ERROR_NOT_ENOUGH_QUOTA
。但是,你使用静态缓冲区应该不会有这个问题。
如果您正在读取磁盘上的文件,而不是控制台流,您可能会 map it to memory, 消除任何中间缓冲并根据需要加载文件部分,通过与虚拟内存相同的机制。
如果您尝试读取标准输入 binary
您需要的数据:
- 设置
_setmode( _fileno( stdin), _O_BINARY);
- 和
fread( buf, 1, bufSize, stdin)
看看我的类似解决方案
应用程序通过 stdin
、油门速度和
将它输出到 stdout
.
我正在尝试在 Windows 上用 C++ 高效地从标准输入读取数据,这意味着最好是大块读取。这可以通过以下方式完成:
ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, bytestoread, &bytesread, 0);
或
read(0, buf, bytestoread);
但在这两种情况下,它仅在 bytestoread
设置为非常小的数字时有效,例如50;如果设置为更大的数字,例如一兆字节,调用失败并出现 'not enough space' 错误,就好像数据没有直接进入我提供的缓冲区,而是通过一些固定大小的内部缓冲区复制。无论输入是通过管道还是在控制台上输入,都是如此。
Windows 是否仅限制进程一次可以从 stdin 读取的块大小?如果是这样,保证工作的最大块大小是多少?
显示问题的完整程序:
#include <errno.h>
#include <io.h>
#include <stdio.h>
#include <string.h>
char buf[1000000];
int main(int argc, char **argv) {
auto r = read(0, buf, sizeof buf);
if (r < 0)
perror("read");
return 0;
}
据我所知,是stdin
没有限制。它作为一个无尽的流工作,应该提供你需要的尽可能多的存储空间。我看到的唯一选择是您正在使用的内核在某些时候会阻塞
您没有说明您使用的是哪个版本的运行时和 OS,但我无法在 Windows 10 上使用 MSVC 19.16.27031.1 重现此问题。有一些记录在案的原因可能会失败。来自 MSDN documentation of ReadFile
:
Characters can be read from the console input buffer by using
ReadFile
with a handle to console input. The console mode determines the exact behavior of theReadFile
function. By default, the console mode isENABLE_LINE_INPUT
, which indicates thatReadFile
should read until it reaches a carriage return. If you press Ctrl+C, the call succeeds, butGetLastError
returnsERROR_OPERATION_ABORTED
. For more information, seeCreateFile
.
还有另一种方法可能会导致此错误,与异步有关 I/O,但这似乎不是这里的问题。您可能想用 SetConsoleMode
关闭 ENABLE_LINE_INPUT
标志。该文档还说,如果无法锁定缓冲区的内存页面,调用可能会失败并返回 ERROR_NOT_ENOUGH_QUOTA
。但是,你使用静态缓冲区应该不会有这个问题。
如果您正在读取磁盘上的文件,而不是控制台流,您可能会 map it to memory, 消除任何中间缓冲并根据需要加载文件部分,通过与虚拟内存相同的机制。
如果您尝试读取标准输入 binary
您需要的数据:
- 设置
_setmode( _fileno( stdin), _O_BINARY);
- 和
fread( buf, 1, bufSize, stdin)
看看我的类似解决方案
应用程序通过 stdin
、油门速度和
将它输出到 stdout
.