- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
TL;DR:为什么 freopen(NULL, "rb", stdin)
在 Windows 上总是失败?
我正在尝试用 C 语言重新实现一个 base64
编码器,它从 stdin 获取输入并将编码后的等价物输出到 stdout。我有一个问题in my previous post其中 fread
过早地发出 EOF 信号。这是我的主要方法:
int main(void)
{
unsigned char buffer[BUFFER_SIZE];
unsigned char base64_buffer[BASE64_BUFFER];
while (1)
{
TRACE_PUTS("Reading in data from stdin...");
size_t read = fread(buffer, 1, sizeof(buffer), stdin); /* Read the data in using fread(3) */
/* Process the buffer */
TRACE_PRINTF("Amount read: %zu\n", read);
TRACE_PUTS("Beginning base64 encode of buffer");
size_t encoded = base64_encode(buffer, read, base64_buffer, sizeof(base64_buffer));
/* Write the data to stdout */
TRACE_PUTS("Writing data to standard output");
...
if (read < sizeof(buffer))
{
break; /* We reached EOF or had an error during the read */
}
}
if (ferror(stdin))
{
/* Handle errors */
fprintf(stderr, "%s\n", "There was a problem reading from the file.");
exit(1);
}
puts(""); /* Output a newline before finishing */
return 0;
}
本质上,它使用 fread
从 stdin 读取数据,编码为 base64,将其写入 stdout,然后在循环结束时检查是否到达 EOF。
当我将二进制文件的内容通过管道传输到此应用程序的标准输入时,它只会读取文件总字节数的一小部分。例如:
$ cat /bin/echo | my_base64_program >/dev/null # only view the trace output
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin...
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 600
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin...
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 600
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin...
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 600
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output
TRACE: C:/Users/James/Code/c/base64/main.c:23: Reading in data from stdin...
TRACE: C:/Users/James/Code/c/base64/main.c:28: Amount read: 569
TRACE: C:/Users/James/Code/c/base64/main.c:29: Beginning base64 encode of buffer
TRACE: C:/Users/James/Code/c/base64/main.c:43: Writing data to standard output
$ cat /bin/echo | wc -c
28352
如您所见,/bin/echo
有 28352 个字节长,但只有约 2400 个字节被处理。我认为原因是因为 stdin 未被视为二进制文件,因此某些控制字符(如链接帖子的答案中提到的 Control-Z)过早地发出 EOF 信号。
我看了一下 base64 source code看起来他们正在使用 xfreopen
(它只是 freopen
的包装器)告诉 fread
将标准输入解释为二进制。所以我在 while 循环之前继续这样做:
if (!freopen(NULL, "rb", stdin))
{
fprintf(stderr, "freopen failed. error: %s\n", strerror(errno));
exit(1);
}
但是,现在我的应用程序总是在此时退出:
$ cat /bin/echo | my_base64_program
freopen failed. error: Invalid argument
那么为什么 freopen
在那个时候失败了,当它适用于 base64
时?如果相关的话,我在 Windows 上将 MinGW-w64 与 GCC 结合使用。
最佳答案
freopen()
通常会失败C 标准说:
If
filename
is a null pointer, thefreopen
function attempts to change the mode of thestream
to that specified bymode
, as if the name of the file currently associated with the stream had been used. It is implementation-defined which changes of mode are permitted (if any), and under what circumstances.
据推测,您的实现不允许您尝试进行的更改。例如,在 Mac OS X 上,freopen()
的手册页添加了:
The new mode must be compatible with the mode that the stream was originally opened with:
- Streams originally opened with mode "r" can only be reopened with that same mode.
- Streams originally opened with mode "a" can be reopened with the same mode, or mode "w".
- Streams originally opened with mode ``w'' can be reopened with the same mode, or mode "a".
- Streams originally opened with mode "r+", "w+", or "a+" can be reopened with any mode.
话虽如此,在 Mac OS X 上(无论如何 b
都是空操作),你会没事的。
freopen()
在 Windows 上特别失败但是,您使用的是 Windows。您需要学习如何查找和阅读文档。我使用带有术语“site:msdn.microsoft.com freopen”的 Google 搜索来查找我正在寻找的任何功能。该特定搜索产生了 freopen()
的手册它说:
If
path
,mode
, orstream
is a null pointer, or if filename is an empty string, these functions invoke the invalid parameter handler, as described in Parameter Validation. If execution is allowed to continue, these functions set errno to EINVAL and return NULL.
这是记录在案的行为:这也是您所看到的行为。您的系统手册很有帮助。它基本上是在说“你不应该”。
我注意到在我的 answer到你的previous question ,我指向 _setmode()
:
However, it is more likely that you need
_setmode()
:_setmode(_fileno(stdin), O_BINARY);
这是在 question 的答案中给出的建议那deamentiaemundi指向。
我顺便注意到 setmode()
的 Microsoft 手册页说:
This POSIX function is deprecated. Use the ISO C++ conformant
_setmode
instead.
这是一个奇怪的评论,因为 POSIX没有标准化功能setmode()
首先。
您可以找到 Microsoft 的 fileno()
文档.它也有关于 POSIX 的介绍(但这次它是准确的;POSIX 确实指定了 fileno()
)并建议您引用 _fileno()
.
关于c - 我想将 stdin 解释为二进制文件。为什么 freopen 在 Windows 上失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39339164/
编辑:我已经成功缩小了问题范围,但对我来说仍然没有多大意义。我的代码变成8行: int savedOut = dup(1); printf("Changing the outstream to p
我是 C++ 的初学者,我有一个超出我能力范围的问题。我在 GNU GCC 下编译。我用 #include 也称为: #include 在我的程序中的某个时刻,我告诉程序使用文件 de_facut.t
知道为什么会这样: #include #include int nrpart; int k; void main() { printf("lol"); freopen("p2.in
我正在使用我的共享库将 freopen 用于 GUI 应用程序,这样我就可以将调试消息从 stdout 重定向到一个文件 我一直在使用基于 C++ 引用站点片段的代码: /* freopen exam
我正在编写一个 Qt GUI 应用程序(用于进行 XSL 转换)。要将错误消息打印到文件,我正在使用如下调用: freopen("my-error-file.txt", "w", stderr); /
给定以下函数: freopen("file.txt","w",stdout); 将 stdout 重定向到一个文件中,如何使 stdout 重定向回控制台? 我会注意到,是的,还有其他类似的问题,但是
我在执行 2 个连续的 freopen 时遇到错误,file1 包含偶数个整数 int x, y; freopen("file1", "r", stdin); while (cin >> x) {
我正在尝试使用文件重定向 stdout 和 stderr 的输出。我正在使用 freopen,它会在正确的目录中创建文件,但文件是空白的。当我注释掉重定向 stdout 和 stderr 的代码时 -
试图implement freopen() ,据我所知,我在标准中找到了一条实际上没有指定任何内容的规范。 所以... freopen()将关闭流(忽略错误),清除其错误和 EOF 标志,重置宽方向,
我有一个程序,该程序获取两个路径作为命令行参数。第一个参数(实际上是第二个参数,因为第一个是命令名称本身)是程序从中读取文件(输入文件)的路径。第二个是程序写入的文件(输出文件)的路径。 int ma
目前,这是我创建的代码,但我似乎找不到其背后的问题。我正在编写一个加密程序 int countWords(FILE *f){ int count = 0; char ch; whil
我正在尝试使用 freopen 写入子目录内的文件: freopen("output/output-1.txt", "w", stdout); 我尝试将其更改为输出到当前目录并且它有效。当目标输出文件
我有一堆批处理文件,用程序 A 做这样的事情: A > log.txt ; grep 'result:' log.txt > result.txt || raise_hell.sh 我想做的是修改 A
我正在尝试创建一个文件,其名称是一个字符串常量,但是一个由常量字符串“List”组成的字符串,一个整数++ 一个扩展名。这是我的代码: #include #include #include #i
来自 In multi thread application how can i redirect stderr & stdout in separate file as per thread? 的扩
这是 How to capture output of printf? 的后续行动- 特别是 jxh 的回答。 我在 Viesturs 在 2018 年的答案中遇到了同样的问题。有人建议他打开一个新问
freopen 的签名是FILE * freopen (const char * filename, const char * mode, FILE * stream) 根据文档,返回值与 strea
我尝试编译并运行具有以下几行的 C 代码: FILE *preproc_producer = NULL; preproc_producer = tmpfile(); // preproc_produc
你好,我想知道在我调用之后我们如何再次从 stdin 获取输入: freopen("Smefile.txt","r",stdin); 准确地说,我希望我的程序的第一个部分应该从指定的文件中获取输入,下
我尝试使用以下命令从标准输出重定向我的 C++ 程序中的输出: freopen(cmd.c_str(),"w",stdout); 然后调用system执行cmd。我也尝试过 fork 然后调用
我是一名优秀的程序员,十分优秀!