提问人:John Forkosh 提问时间:11/15/2016 最后编辑:John Forkosh 更新时间:11/16/2016 访问量:1614
将 stdout 置于二进制模式的可移植方式
Portable way to put stdout in binary mode
问:
我正在编写用作 cgi 的 C 程序,用于生成和输出 gif 图像。它们用于带有 form 的标签的 HTML 页面中,其中查询字符串参数描述了要由 CGI 生成的图像。<img src="/cgi-bin/gifprogram.cgi?param=val&etc">
像这样调用的 C 程序 cgi 会将其输出发送到 stdout。在本例中,输出是包含大量二进制(不可打印)字节的 gif 图像。这在 Unix/Linux 上已经运行良好。但 Windows 显然需要一个单独的非可移植调用(以及一些特定于 Windows 的调用)。否则,您会遇到通常的 cr/lf 问题,即每个0x0A前面都有一个虚假0x0D。这在 gif :(中看起来并不好_setmode(_fileno(stdout),_O_BINARY)
#include
是否有任何可移植的方法来解决这个问题,使用ANSI标准的C,没有任何特定于平台的语法,并且没有很多东西来尝试检测Windows编译环境?此外,一些 Windows 编译器显然使用,而另一些编译器则使用 ,我还必须尝试检测。#ifdef
_setmode(_fileno(stdout),_O_BINARY)
setmode(fileno(stdout),O_BINARY)
>>编辑<<回复评论...
谢谢,伙计们。我显然不得不采用一些完全符合 posix 的/可移植的程序,并将它们用于 Windows [注意,JoNaThAn:真的,不需要编辑来大写:),——我个人的写作风格是故意在语法上松散的]。
以下是我正在考虑引入的一些愚蠢的第一部分。据我所知,使用 mingw 似乎有效。它是否足够,即适用于所有或大多数其他编译器?是否有必要,即任何简短整洁/快速和肮脏的方法来用更少/更易读的代码行来完成同样的事情?
/* ---
* windows-specific header info
* ---------------------------- */
#ifndef WINDOWS /* -DWINDOWS not supplied by user */
#if defined(_WINDOWS) || defined(_WIN32) || defined(WIN32) \
|| defined(DJGPP) /* try to recognize windows compilers */ \
|| defined(_USRDLL) /* must be WINDOWS if compiling for DLL */
#define WINDOWS /* signal windows */
#endif
#endif
#ifdef WINDOWS /* Windows opens stdout in char mode, and */
#include <fcntl.h> /* precedes every 0x0A with spurious 0x0D.*/
#include <io.h> /* So emitcache() issues a Win _setmode() */
/* call to put stdout in binary mode. */
#if defined(_O_BINARY) && !defined(O_BINARY) /* only have _O_BINARY */
#define O_BINARY _O_BINARY /* make O_BINARY available, etc... */
#define setmode _setmode
#define fileno _fileno
#endif
#if defined(_O_BINARY) || defined(O_BINARY) /* setmode() now available */
#define HAVE_SETMODE /* so we'll use setmode() */
#endif
#if defined(_MSC_VER) && defined(_DEBUG) /* MS VC++ in debug mode */
/* to show source file and line numbers where memory leaks occur... */
#define _CRTDBG_MAP_ALLOC /* ...include this debug macro */
#include <crtdbg.h> /* and this debug library */
#endif
#define ISWINDOWS 1
#else
#define ISWINDOWS 0
#endif
而后续的相应代码,确保 stdout 处于二进制模式是
#if ISWINDOWS /* compiling for win... */
#ifdef HAVE_SETMODE /* try to use setmode()*/
if ( setmode ( fileno (stdout), O_BINARY) /* to set stdout */
== -1 ) /* handle error here*/ ; /* to binary mode */
#else /* setmode not available */
#if 1 /* so try this...*/
freopen ("CON", "wb", stdout); /* freopen stdout binary */
#else /* or maybe this... */
stdout = fdopen (STDOUT_FILENO, "wb"); /*fdopen stdout binary*/
#endif /* done */
#endif /* " */
#endif /* " */
您会注意到我正在尝试建议 setmode() 替代方案。虽然我的替代测试没有成功,但我保留了语法以备将来参考,以防万一其中一些最终被证明是有用的。
答: 暂无答案
评论
setmode()
_setmode()
_setmode()
setmode()
CON:
void setbinmode(FILE *fp)