为何Windows的_read()函数无法从STDOUT读取?能否实现该操作?
问题
在Linux系统中我可以用read()从STDOUT读取数据,但Windows系统似乎只允许从STDIN读取、向STDOUT写入。我在Windows上运行了以下代码:
#include <io.h> // Include for _read() #include <stdio.h> #include <string.h> #include <stdio.h> int main() { char buffer[256]; int n; int fd = 1; // File descriptor for stdout (standard output) while ((n = _read(fd, buffer, sizeof(buffer) - 1)) > 0) { buffer[n] = '\0'; // Null-terminate the string if needed char* p = buffer; char* nl; while ((nl = strchr(p, '\n')) != NULL) { *nl = '\0'; // Null-terminate the line printf("Line: %s\n", p); // Process the line p = nl + 1; // Move to the next line } // If there's any remaining data in the buffer, process it if (*p != '\0') { printf("Remaining: %s\n", p); } } if (n == 0) { // End of input (Ctrl+Z on Windows) printf("End of input reached. Program exiting.\n"); } else { perror("Error reading from stdin"); } return 0; }
运行后报错:Error reading from fd: Bad file descriptor。想知道:
- 为什么Linux与Windows的行为存在差异?
- 能否在Windows上用
_read()从STDOUT读取数据?
解答
1. Linux与Windows的行为差异原因
核心差异源于两个系统的标准句柄模型设计不同:
- 在Linux中,遵循「一切皆文件」的设计理念,标准输入(0)、输出(1)、错误(2)本质都是指向内核文件对象的描述符。当程序在终端运行时,stdout和stdin实际上指向同一个终端设备文件(比如
/dev/tty),而终端设备是双向可读写的。这时候调用read(1, ...)本质是从终端设备读取数据,和read(0, ...)效果一致;如果stdout被重定向到其他双向对象(比如socket),也能读取数据。 - 在Windows中,标准句柄是严格单向的:STDIN(文件描述符0)被打开为只读模式,STDOUT(1)和STDERR(2)被打开为只写模式。它们对应的内核对象(比如控制台的输入缓冲区和输出缓冲区)是完全分离的,没有读取权限的句柄调用
_read()自然会返回「无效文件描述符」错误。
2. Windows上能否用_read()从STDOUT读取数据?
不能直接这么做。Windows的STDOUT句柄本身不具备读取权限,任何尝试用_read()(或底层Win32 APIReadFile())读取STDOUT的操作都会失败。
如果你的需求是读取控制台输入,直接使用文件描述符0(STDIN)即可;如果是想捕获当前程序自己输出到STDOUT的内容,可以通过管道重定向的方式实现:创建一个匿名管道,将STDOUT重定向到管道的写端,然后从管道的读端读取数据——但这已经不是直接读取原始的STDOUT句柄了。
内容的提问来源于stack exchange,提问作者Vishal
相关产品推荐
相关产品推荐

