写了一个程序来查看二进制数据。我是正确地做了这个还是我得到了垃圾数据?

时间:2013-10-25 14:35:28

标签: c arrays binary

本周我的任务是创建一个程序,读取我教授发给我的数据文件。赋值说这个数据中有10个整数我需要写入数组,我已经完成但我不确定它是正确的还是只是垃圾数据。我将为此文件附加一个DL链接(它只有40字节)。我在下面创建了一个程序,它将读取我需要的10个数字,但我怎么知道它是垃圾数据还是真正的交易。我每次都得到相同的数字,这表明我正在做这个吗?我希望将来使用任何长期技巧。

这是DL链接 mysteryData

#include <stdio.h>
#include <string.h>

int main(void)
{
  int i;

  FILE* myFile = NULL;

  myFile = fopen("mysteryData.dat", "rb");

  int Mystery[10] =
  { '\0' };

  if (myFile == NULL )
  {
    printf("Failed to open file\n");
  }
  else
  {
    fread(Mystery, sizeof(int), sizeof(Mystery), myFile);

    printf("%d\n", Mystery);
  }

  for (i = 0; i < 9; i++)
  {
    printf("%d\n", Mystery[i]);
  }
  fclose(myFile);
}

2 个答案:

答案 0 :(得分:0)

首先,如果您打算在Mystery来电后打印fread的地址,则应使用%p。其次,也许用十六进制打印可以帮助你看到问题:

% echo $'\x12\x34\x56\x78\x9a\xbc\xde\xff' > mysteryData.dat
% ./test
0x7fff598cfae0 # %p
78563412       # %x
ffdebc9a
a # newline = 0x0a
0
0
0
0
0
0
%

这些值在整数中串联在一起,并按字节顺序反转。它们被串在一起,因为你正在整理它们:

12 34 56 78 9a bc de ff a0 00 00 00
^---------^ ^---------^ ^---------^

由此我们看到编译器中的int是32位(4字节)。此外,交换字节的原因是因为我的系统是小端的;这意味着12是最不重要的8位,34是次最重要的等等。

您可能希望将这些字节作为单个字节进行访问,您应该将Mystery更改为char[10]。并且可能使它更大以确保您有足够的空间。最后,您要检查fread的返回值,它将告诉您实际读取的字节数。


Fread因此被宣布:

fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
                                 ^^^^         ^^^^^^

您正在传递权限size,但是您传递的nitems大小为Mystery,而不是传递nitems*sizeof(int)的项目数。使用

fread(Mystery, sizeof(int), sizeof(Mystery)/sizeof(int), myFile);

或者更好,

fread(Mystery, sizeof(Mystery[0]), sizeof(Mystery)/sizeof(Mystery[0]), myFile);

答案 1 :(得分:0)

首先,它应该指定如何将这些整数存储到文件中。

由于文件是40个字节,并且存在项目计数为10的规范,您可以假设它们存储为二进制数据,每个整数占用四个字节。

*我这样说是因为该文件可能是一个文本文件,整数存储为换行符分隔值:

10

13

4563

-32

等......

但是。在40个字节中,没有10个整数存储为文本的空间,所以假设它们是二进制数据。

此时我们还假设数据的字节顺序与程序编译和运行的体系结构相同。我不会再进一步​​了解更多信息,您可以谷歌搜索 big endian little endian

最后应该指定整数的大小。整数的大小可能因操作系统/体系结构而异:

请参阅What does the C++ standard state the size of int, long type to be?

但我们有40个字节,我们知道我们有10个整数。对于文件,每个数字的int为4个字节。

您可以通过以下方式检查您的架构是否匹配:

printf("Here ints are %d bytes.\n", (int) sizeof(int));

并查看输出。

回到你的代码,有些事情需要调整。见评论......

#include <stdio.h>
#include <string.h>

int main (void)
{
    int i;

    int itemsRead; // we'll use that later...

    FILE* myFile=NULL;

    myFile=fopen("mysteryData.dat", "rb");

    int *Mystery = malloc (sizeof(int) * 10); // It's a better practice...
    //... to allocate the buffers/arrays you need instead of declaring them
    // statically. If your file grows up with millions of numbers your code
    // will still be scalable.

    if(!Mystery) // Just check the alloc succeeded
    {
        printf("Failed to allocate buffer\n");
    }

    if(myFile==NULL)
    {
        printf("Failed to open file\n");
        free( Mystery ); // Free the buffer
        return 0;        // Quit
    }

    itemsRead = fread(Mystery, sizeof(int), 10, myFile);
    // 2nd parameter is size of element
    // 3rd parameter is how many items
    // the function returns the items actually read

    // What is the file was shorter than expected?
    // Check we were able to actually read 10 items of 4 bytes each

    if( itemsRead < 10 )
    {
        printf("The file ended unexpectedly\n");
        free( Mystery ); // Free the buffer
        return 0;        // Quit
    }

    for (i=0; i<10; i++) // 10 Items: count from 0 to 9 so until i<10
    {
        printf("%d\n", Mystery[i]);
    }

    free( Mystery  );
    fclose( myFile );
}