C 中的 fgetc 和 fputc

fgetc and fputc in C

我正在尝试从一个文件的开头复制 5 个字节并将它们放入另一个文件的开头。然而,他们并没有准确地复制。我认为问题出在 fputc 和 fgetc 中,但不确定是什么...

bmpFile = fopen("frog.bmp", "rb");
encodedFile = fopen("encodedFrog.bmp", "rwb");

for (int i=0; i<5; i++){
    fputc(fgetc(bmpFile), encodedFile); //copy that byte, unchanged into the   output
}

//close and open both files, read the first 5bytes back;
fclose(bmpFile);
fclose(encodedFile);
bmpFile = fopen("frog.bmp", "rb");
encodedFile = fopen("encodedFrog.bmp", "rwb");
for (int i=0; i<5; i++){
    unsigned int actual = fgetc(bmpFile);
    unsigned int value = fgetc(encodedFile);
    printf("actual: %d \tvalue: %d\n", actual, value);
}

结果是:

actual: 66  value: 66
actual: 77  value: 77
actual: 54  value: 134
actual: 115     value: 68
actual: 20  value: 17

谢谢

"rwb" 不是有效的 fopen 模式。您可能想使用

fopen("encodedFrog.bmp", "r+b");

这将以二进制模式打开现有文件进行输入和输出。如果文件不存在,你应该使用 "w+b".

fopen("encodedFrog.bmp", "w+b");

这将以二进制模式打开一个用于输入和输出的新文件。

此外,正如@amdixon 提到的,您应该使用 rewind,而不是重新打开文件,这会将流位置重置为开头。

修复 fopen 问题后,您可能需要查看 freadfwrite,它们可以对二进制 read/writes 提供一些额外的错误检查。

虽然二进制 reading/writing 一次一个字符没有错,但对于二进制文件流 input/output 你有额外的功能 freadfwrite允许您读取和写入特定数量的字节(或任何其他 size 值,例如 int,等等)。基本语法是:

size_t fread (void *ptr, size_t size, size_t nmemb, FILE *stream);

size_t fwrite (const void *ptr, size_t size, size_t nmemb,
                FILE *stream);

所以代替:

for (int i=0; i<5; i++){
    fputc(fgetc(bmpFile), encodedFile);
}

您可以使用 freadfwrite 来验证读取和写入的 'size' 元素的数量:

unsigned char buf[5] = {0};

if (fread (buf, 1, 5, bmpFile) == 5) {
    if (fwrite (buf, 1, 5, encodedFile) != 5)
        fprintf (stderr, "error: fwrite failed for encodedFile.\n");
}
else
    fprintf (stderr, "error: fread failed for bmpFile.\n");

一个简单的例子可能是:

#include <stdio.h>

int main (int argc, char **argv) {

    FILE *in, *out;
    unsigned char buf[8] = {0};
    unsigned char chr[8] = {0};
    size_t i;

    if (argc < 3) {
        fprintf (stderr, "error: insufficient input.  prog infile outfile (binary cp)\n");
        return 1;
    }

    if (!(in = fopen (argv[1], "r+b")) || !(out = fopen (argv[2], "w+b"))) {
        fprintf (stderr, "error: file open failed.\n");
        return 1;
    }

    if (fread (buf, 1, 5, in) == 5) {
        if (fwrite (buf, 1, 5, out) != 5)
            fprintf (stderr, "error: fwrite failed for encodedFile.\n");
    }
    else
        fprintf (stderr, "error: fread failed for bmpFile.\n");

    rewind (in);
    rewind (out);

    if (fread (buf, 1, 5, in) != 5 || fread (chr, 1, 5, out) != 5) {
        fprintf (stderr, "error: read after rewind failed.\n");
        return 1;
    }

    fclose (in);
    fclose (out);

    for (i = 0; i < 5; i++)
        printf (" actual : %3hhu   value : %3hhu\n", buf[i], chr[i]);
    putchar ('\n');

    return 0;
}

Example/Output

$ ./bin/freadfwrite bin/xpathfname bin/ytestout
 actual : 127   value : 127
 actual :  69   value :  69
 actual :  76   value :  76
 actual :  70   value :  70
 actual :   2   value :   2