【问题标题】:Reading a file 16 bytes at a time in C在 C 中一次读取 16 个字节的文件
【发布时间】:2014-12-12 07:18:44
【问题描述】:

我正在尝试一次读取从命令行参数解析的文件 16 个字节。我将字节存储在一个无符号字符数组中。然后我尝试以 HEX 格式打印元素,然后,如果它们是可打印字符,我正在打印它们,如果不是,我正在打印一个点“。”我还想在每个新行上打印文件开头的字节偏移量,但我想在开始处理之前让其余部分工作。我遇到的问题是我正在读取的文件没有打印,所以我认为我做的不对。我开始使用fread(),但我想我可能需要使用fseek(),但我不确定。如果有人能指出我正确的方向或告诉我是否做错了什么,我将不胜感激。

代码:

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

int main(int argc, char *argv[])
{
    FILE *fp;

    int i, j;

    unsigned char buffer[17];

    fp = fopen(argv[1], "r");

    while(!feof(fp))
    {
        while(fread(buffer, 16, 1, fp) !=0)
        {

            for(i=0; i < 16; i++)
            {
                printf("%X ", buffer[i]);
            }

            for(j = 0; j < 16; j++)
            {
                if(isprint(buffer[j]))
                    printf("%s", buffer[j]);
                else
                    printf("." );
            }

            printf("\n");
        }
    }

    fclose(fp);

    return 0;
}

预期输出:

0001:  40 4F 28 37 0B B8 FF 9D 81 5E 2E 73 B5 CC 6A 70 @O(7.....^.s..jp
0010: 0F 30 9C 6E 7E F7 53 E0 C1 5E 9A 38 C5 02 F2 33 .0.n .S..^.8...3

编辑:修正了建议的问题。以文本模式而不是二进制模式打开文件。将读取模式更改为"rb",代码现在可以正常工作了。

【问题讨论】:

    标签: c file hex offset


    【解决方案1】:

    您需要以二进制模式打开文件,在文本模式下对文件使用 fseek/ftell 会给出不稳定的值。

    所以打开文件

    fp = fopen(argv[1], "rb");
    

    另一个好的做法是始终通过检查返回值来检查函数是否成功,在本例中为if (fp != NULL) ...

    而不是读取 16 字节块读取 1 字节 16 次,否则如果文件长度不能被 16 整除,您会错过最后一个字节

    if ( fp != NULL )
    {
      int read = 0;
      while((read = fread(buffer, 1, 16, fp)) > 0)
      {
        for(i=0; i < read; i++)
        {
        ...
      }
      fclose(fp);
    }
    

    IOW不需要外接while (feof(fp)) ...

    printf("%s", buffer[j]);
    

    你没有使用正确的格式说明符,buffer[j] 是一个字符,而不是一个字符串所以写

    printf("%c", buffer[j]);
    

    编辑:如果您不在某些嵌入式环境中,一次读取 16 个字节的最小堆栈不是那么有效,您可以像读取 2k 或更大的大小以更快地读取。

    【讨论】:

    • 啊,好吧,我知道我哪里出错了。修复了它现在可以正确打印。现在我将开始处理文件偏移量。你知道fseek()fread() 是否也能做到这一点?
    • @wh33lybrdy 使用 fseek 在文件中定位。您可以根据第二个参数指定从开始或结束的偏移量,例如SEEK_END。如果您有更多问题,最好发布它们而不是继续编辑这个问题,因为一段时间后这个问题会变得非常难以阅读。
    猜你喜欢
    • 1970-01-01
    • 2015-12-11
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    • 2011-08-30
    相关资源
    最近更新 更多