逐字节打印

时间:2018-09-19 13:24:55

标签: c

我试图制作一个C文件,该文件打开一个文件,并使用每个字节的十六进制格式(%02x)逐字节打印其文件。

结果应该是这样的:

$ ./hexabyte file
43
3d
67
...

我知道我想使用fread来做到这一点,但是我不确定为什么该解决方案不起作用:

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


int args_test(int args, char path[]){

  if(args < 1){
    fprintf(stderr, "Usage: %s path\n", path);
    exit(EXIT_SUCCESS);
  }
  if(args < 2){
    fprintf(stderr, "Usage: %s path\n", path);
    exit(EXIT_SUCCESS);
  }

  if(args > 2){
    fprintf(stderr, "Usage: %s path\n", path);
    exit(EXIT_SUCCESS);
  }

  return 0;
}


int open_file(char path[]){
  FILE *fp;
  fp = fopen(path, "r");
  char buffer[1000];

  if(!fp){
    fprintf(stderr, "%s\n", strerror(errno));
    return EXIT_FAILURE;
  }

  fseek(fp, 0, SEEK_END);
  int len = ftell(fp);

  //Why does it not reach this loop?
  while (fread(buffer, strlen(path), 1, fp) == 1){
    printf("%02x hexabytes\n", len);
  }

  fclose(fp);

  exit(EXIT_SUCCESS);
}

int main(int args, char* argv[]){
  if(args < 2 || args > 2){
    args_test(args, argv[0]);
  }
  args_test(args, argv[1]);
  open_file(argv[1]);
  exit(EXIT_SUCCESS);
}

似乎它从未到达我的while循环,因此也从不打印任何内容

3 个答案:

答案 0 :(得分:1)

您需要将文件指针重置为文件的开头:

fseek(fp, 0, SEEK_SET);

答案 1 :(得分:1)

您要搜索文件的末尾,因此fread将没有任何内容可读取。您需要重新开始。

fread也被要求读取路径的长度,这似乎是错误的,您的循环设置方式似乎是一次仅1个字节。

fseek(fp, 0, SEEK_END); // Seeks to end of file
int len = ftell(fp);

// Nothing to read, at end
while (fread(buffer, strlen(path), 1, fp) == 1){
    printf("%02x hexabytes\n", len);
}

ftell之后再次寻求。

fseek(fp, 0, SEEK_END); // Seeks to end of file
int len = ftell(fp);
fseek(fp, 0, SEEK_SET); // Go to start again
// Read from start, 1 byte at a time
char byte;
while (fread(&byte, 1, 1, fp) == 1){
    printf("%02X\n", (int)byte);
}

您也可以一次读取1000个字节(如buffer一样),但是随后需要第二个循环,或者可以读取整个文件,但是需要动态分配缓冲区({{1 }}。

答案 2 :(得分:1)

即使您解决了fseek问题,也遇到了其他问题:

while (fread(buffer, strlen(path), 1, fp) == 1){
  printf("%02x hexabytes\n", len);
}

请注意,您不会一次读取一个字节;而是一次读取一个字节。您一次读取的是strlen(path)大小的块中的字节。

您也不打印刚刚读取的字节;您正在打印文件的长度。因此,假设您的文件大小为65536字节,您将获得输出

10000 hexabytes
10000 hexabytes
10000 hexabytes
...

65536 / strlen(path)次。我认为那不是你想要的。

我认为您要追求的是这些方面的更多东西:

unsigned char buffer[1000]; // for arbitrary bytes, unsigned char works better.

int bytes_read = 0;

while ( (bytes_read = fread( buffer, 1, sizeof buffer, fp )) != EOF )
{
  for( int b = 0; b < bytes_read; b++ )
  {
    printf( "%02hhx\n", buffer[b] ); // %x expects unsigned *int*, use the
  }                                  // hh modifier to specify unsigned char
}

表达式

bytes_read = fread( buffer, 1, sizeof buffer, fp )

sizeof buffer读取多达fp(在这种情况下为1000)字节,并将实际读取的数字存储到bytes_read。如果我们没有击中EOF,那么我们将打印buffer的内容。