C了解二进制标准输入(C read binary stdin)

2019-08-22 19:00发布

我试图建立一个指令流水线模拟器,我有很多的麻烦开始。 我需要做的是阅读从标准输入的二进制,然后将其存储在内存中不知何故,而我操纵数据。 我需要准确的32位一前一后的大块阅读。

我如何在正好32位的块一次读? 其次,如何将其存储操作以后呢?

这里就是我这么远,但检查二进制块我继续读下去,它只是看起来不正确的,我不认为我在读正好32位,正如我需要。

char buffer[4] = { 0 }; // initialize to 0
unsigned long c = 0;
int bytesize = 4; // read in 32 bits
while (fgets(buffer, bytesize, stdin)) {
  memcpy(&c, buffer, bytesize); // copy the data to a more usable structure for bit manipulation later
  // more stuff
  buffer[0] = 0; buffer[1] = 0; buffer[2] = 0; buffer[3] = 0; // set to zero before next loop
}
fclose(stdin);

如何在32位在同一时间(他们都是1/0,没有换行等),以及我该怎么存放它,是阅读char[]好吗?

编辑:我能够读取二进制文件,但没有一个答案产生正确的顺序位 - 他们都错位了,我怀疑字节顺序和问题读,在时间中移动8位(1个字符) - 此需要在Windows和C工作...?

Answer 1:

你需要的是freopen() 从手册页:

如果文件名是一个空指针,调用freopen()函数将试图流的模式改变为mode指定,仿佛已经使用当前与流相关联的文件的名称。 在这种情况下,与流相关的文件描述符不必如果调用freopen函数关闭()成功。 它是实现定义允许哪些模式变化(如果有的话),以及在什么情况下。

基本上,你真的可以做到最好是这样的:

freopen(NULL, "rb", stdin);

这将重新打开stdin是相同的输入流,但在二进制模式。 在正常模式下,读取stdin上的Windows将其转换\r\n (换行符的Windows)与单个字符的ASCII 10.使用"rb"模式禁用此转换,这样就可以在二进制数据正确读取。

freopen()返回一个文件句柄,但它的前值(我们把它放在二进制模式之前),所以不要使用它的任何东西。 在此之后,使用fread()如已经提到。

至于您的问题,但是,您可能不会在“32位”阅读,但如果您使用fread()在4读取char秒(这是你可以在C做的最好的- char是保证至少 8位,但一些历史和嵌入式平台具有16位的char S(有的甚至有18或更坏))。 如果您使用fgets()你将永远不会在4个字节读取。 你会读到至少3(取决于他们中是否有新行),而第4个字节将是'\0' ,因为C字符串是空终止,并fgets() NUL,终止其在读什么(是个不错的功能)。 显然,这是不是你想要的,所以你应该使用fread()



Answer 2:

考虑使用SET_BINARY_MODE宏观和setmode

#ifdef _WIN32
# include <io.h>
# include <fcntl.h>
# define SET_BINARY_MODE(handle) setmode(handle, O_BINARY)
#else
# define SET_BINARY_MODE(handle) ((void)0)
#endif

有关详细信息SET_BINARY_MODE宏在这里:“ 通过标准I / O处理二进制文件 ”

有关详细信息setmode这里: “_setmode ”



Answer 3:

与fgets()是所有错在这里。 它旨在通过结束行字符,而不是二进制数据端的人可读的ASCII文本,并不会得到你所需要的。

我最近做正是你想要使用什么样的read()调用。 除非你的程序已经明确关闭标准输入,第一个参数(文件描述符),你可以设置为0的恒定值标准输入。 或者,如果你是一个POSIX系统(在Linux,Mac OS X或Unix的一些其他现代变体)上,您可以使用STDIN_FILENO。



Answer 4:

我不得不从善良的人上面的各种意见拼凑答案,所以这里是一家运作完全正常的工作样本 - 仅适用于Windows,但您可以在Windows的具体的东西可能转化为您的平台。

#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "windows.h"
#include <io.h>
#include <fcntl.h>

int main()
{
    char rbuf[4096];
    char *deffile = "c:\\temp\\outvideo.bin";
    size_t r;
    char *outfilename = deffile;
    FILE *newin;

    freopen(NULL, "rb", stdin);
    _setmode(_fileno(stdin), _O_BINARY);

    FILE *f = fopen(outfilename, "w+b");
    if (f == NULL)
    {
        printf("unable to open %s\n", outfilename);
        exit(1);
    }

    for (;; )
    {
        r = fread(rbuf, 1, sizeof(rbuf), stdin);
        if (r > 0)
        {
            size_t w;
            for (size_t nleft = r; nleft > 0; )
            {
                w = fwrite(rbuf, 1, nleft, f);
                if (w == 0)
                {
                    printf("error: unable to write %d bytes to %s\n", nleft, outfilename);
                    exit(1);
                }
                nleft -= w;
                fflush(f);
            }
        }
        else
        {
            Sleep(10); // wait for more input, but not in a tight loop
        }
    }

    return 0;
}


Answer 5:

I don't know what OS you are running, but you typically cannot "open stdin in binary". You can try things like

int fd = fdreopen (fileno (stdin), outfname, O_RDONLY | OPEN_O_BINARY);

to try to force it. Then use

uint32_t opcode;
read(fd, &opcode, sizeof (opcode));

But I have no actually tried it myself. :)



Answer 6:

FREAD()适合最适合读取二进制数据。

是的,字符数组是OK,如果你打算处理这些逐字节。



Answer 7:

我有它正确的第一次,但我再用ntohl需要... ÇEndian的转换:点点滴滴



文章来源: C read binary stdin
标签: c binary stdin