如何使void指针读取二进制文件的给定部分

时间:2017-12-15 13:48:37

标签: c struct io binaryfiles

我有一个二进制文件,其中包含3个不同的结构和一个圣诞文本。在二进制文件的第一行,他们为我提供了一个int,它表示文件中包的大小。一个包包含3个结构,chistmastext和大小。 结构位于一个名为framehdr.h的文件中,我正在读取的二进制文件称为TCPdump。

现在我正在尝试创建一个程序att将一次读取每个包然后撤回文本。 我从这样的事情开始:

#pragma warning(disable: 4996)
#include <stdio.h>
#include <stdlib.h>
#include "framehdr.h"
#include <crtdbg.h>

int main()
{
  _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  FILE *fileOpen;
  char *buffer;
  size_t dataInFile;
  long filesize;

  // The three structs
  struct ethernet_hdr ethHdr;
  struct ip_hdr ipHdr;
  struct tcp_hdr tcpHDr;

  fileOpen = fopen("C:\\Users\\Viktor\\source\\repos\\Laboration_3\\Laboration_3\\TCPdump", "rb");
  if (fileOpen == NULL)
  {
    printf("Error\n");
  }
  else
  {
    printf("Success\n");
  }

  char lenOf[10];
  size_t nr;
  // Reads until \n comes 
  fgets(lenOf, sizeof(lenOf), fileOpen);
  sscanf(lenOf, "%d", &nr);
  // Withdraw the size of a package and check if it's correct
  printf("Value: %d\n", nr);
  printf("Adress: %d\n", &nr);

  void *ptr;
  fread(&ptr, nr, 1, fileOpen);
  int resEth = 14;
  printf("resEth: %d\n", resEth);
  int resIP = IP_HL((struct ip_hdr*)ptr);
  printf("ResIP: %d\n", resIP);
  int resTcp = TH_OFF((struct tcp_hdr*)ptr);
  printf("tcpIP: %d\n", resTcp);
  int res = resEth + resIP + resTcp;
  printf("Total: %d", res);

  fclose(fileOpen);
  //free(buffer);

  system("pause");

  return 0;
}

我知道第一个struct ethernet的大小总是14,但我需要得到另外2个的大小,我想要使用IP_HL和TH_OFF。

但我的问题在于我似乎无法将整个包装读到一个 无效*与恐惧。我注意到了我的* ptr。 当我尝试将void *转换为其中一个结构时,这会导致代码中断。

我对虚空*做错了什么?

1 个答案:

答案 0 :(得分:3)

两个问题:

首先,在阅读二进制文件时,您不应该真正使用文本函数。二进制文件确实没有&#34; line&#34;从某种意义上说,文本文件有它。

其次,用

void *ptr;
fread(&ptr, nr, 1, fileOpen);

您正在将指针传递给指针变量,您实际上并未将任何内容读入内存,然后使ptr指向该内存。现在发生的是fread函数将从文件读取nr个字节,然后将其写入&ptr指向的内存,这将导致未定义的行为< / em> if nr > sizeof ptr(因为那时数据将被写出界限)。

你必须分配nr字节的内存,然后将指针传递给它的第一个元素:

char data[nr];
fread(data, nr, 1, fileOpen);

您还应该养成检查错误的习惯。如果fread函数失败怎么办?或者文件被截断并且还没有nr个字节可供阅读?

您可以通过查看fread 返回的内容来检查这些条件。

不仅要检查fread,还有比fopen更多的功能可能会失败。