【问题标题】:Reading a binary file in C: ftell returns results that sometimes are off by one读取 C 中的二进制文件: ftell 返回的结果有时相差 1
【发布时间】:2011-06-01 20:34:08
【问题描述】:

我正在尝试读取以下格式的二进制文件:

图像数量 [4-byte int]

宽度 [4 字节整数]
高度 [4 字节整数]
灰度数据 [宽 * 高字节]
(更多相同类型的元素)

这是第一个被调用的函数:

int process_file(const char *filename) {
    FILE *input_file = fopen(filename, "r");

    //Get number of images
    unsigned int number_of_images = read_int_from_file(input_file);

    //Allocate memory for all images
    struct image *images = malloc(sizeof(struct image) * number_of_images);

    read_images(images, number_of_images, input_file)
}

下面是image 结构,任何人都想知道:

struct image {
    unsigned int width;
    unsigned int height;
    unsigned char *data;
};

这就是read_int_from_file 所做的:

static unsigned int read_int_from_file(FILE *file) {
    unsigned char chars[4];
    if (fread(&chars, sizeof(char), 4, file) != 4) {
        fprintf(stderr, "Couldn't read enough bytes!\n");
        return 0;
    }
    //Calculations follow that return right numbers
    return out;
}

剩下的就这些了:

static int read_images(struct image *images, unsigned int number_of_images, FILE * file) {
    struct image *current_image = images;

    int i;
    for (i = 0; i < number_of_images; i++) {
        read_image(current_image++, file)
    }

    return EXIT_SUCCESS;
}

static int read_image(struct image *image, FILE *file) {
    static long int expected_position = 4;

    if (ftell(file) != expected_position) {
        fprintf(stderr, "Reading @ %lu when should be @ %lu!",
                ftell(file), expected_position);
        exit(EXIT_FAILURE);
    }

    unsigned int width = read_int_from_file(file);
    unsigned int height = read_int_from_file(file);

    unsigned int size = width * height;

    unsigned char *data = malloc(sizeof(char) * size);
    if (data) {
        if (fread(data, sizeof(char), size, file) != size) {
            exit(EXIT_FAILURE);
        }

        image->width = width;
        image->height = height;
        image->data = data;

        expected_position += 2 * 4 + width * height;
        return EXIT_SUCCESS;
    } else {
        exit(EXIT_FAILURE);
    }
}

问题是文件指针有时会在不应该这样做的情况下继续前进,即我正在点击ftell(file) != expected_position。经过大量成功阅读后,我得到了它,但在结束前也有一段时间。

有没有人知道为什么会这样?我的意思是,即使数字是错误的,那也不应该发生,不是吗?谢谢!

【问题讨论】:

    标签: c binary


    【解决方案1】:

    MS-DOS 行尾序列是回车、换行(CR NL0x0D, 0x0A),而 Unix 仅使用换行(NL0x0A)。

    换行

    FILE *input_file = fopen(filename, "r");
    

    FILE *input_file = fopen(filename, "rb");
    

    否则,在 POSIX 标准“IEEE Std 1003.1-1988”之前的 Unix 系统上,fread() 函数用于将 CR NL 转换为 NL

    在 MS-DOS、Windows 和衍生产品上,它会将 NL 转换为 CR NL

    这些翻译导致您对文件位置的看法与ftell() 的计算结果不同。

    【讨论】:

    • 做到了。谢谢!忘记这可能是我太愚蠢了。
    • 我没有按照你的倒数第二段。 在 Unix 上绝对不会发生翻译,因为 POSIX 标准要求文本模式的行为与二进制模式相同。
    • 感谢您的更新。自 1988 年以来,我一直在使用 open() 而不是 fopen()
    • 花了 3 天时间想知道为什么它不起作用,却没有意识到我忘记在 fopen 中添加“b”。非常感谢。
    【解决方案2】:

    你需要这样打开二进制文件:

    //                                   v
    FILE *input_file = fopen(filename, "rb");
    

    【讨论】:

      猜你喜欢
      • 2014-06-10
      • 1970-01-01
      • 1970-01-01
      • 2011-05-08
      • 1970-01-01
      • 2019-05-02
      • 2017-10-01
      相关资源
      最近更新 更多