fread或fwrite给出“错误的文件编号”

Ver*_*ica 0 c gcc fwrite fgets

我在Windows 8.1中使用MinGW,并且我有一个原始数字的输入文本文件(每行一个),我想将它们以二进制形式写入新的二进制文件中。该示例在编译时不会出现以下问题:

gcc -pedantic -Os -c my_code.c -o my_code.exe
Run Code Online (Sandbox Code Playgroud)

但输出是

$ my_code.exe
sh: ./my_code.exe: Bad file number
Run Code Online (Sandbox Code Playgroud)

这是我写的代码:

#include<stdio.h>

int main ()
{
    FILE *fp;
    FILE *prob;
    int length;
    char buffer[30];

   // Open file containing numbers
    if ((prob = fopen("raw_numbers.txt","r")) == NULL)
    {
        printf("Could not open raw_numbers.txt\n");
        exit(1);
    }

    /* Create output binary file */
    fp = fopen( "file.bin" , "w" );

    while( ! feof(prob) )
    {
        fgets(buffer, sizeof(buffer), prob);
        fwrite((const void*) & buffer, 1, sizeof(buffer), fp);
    }

    fclose(prob);
    fclose(fp);
    return(0);
}
Run Code Online (Sandbox Code Playgroud)

使用

$ gcc --version
gcc (GCC) 3.4.4 (msys special)
Run Code Online (Sandbox Code Playgroud)

chq*_*lie 5

您的程序中有多个错误:

  • 您应该测试无法创建输出文件。

  • 您应该测试的返回值fgets()而不是using while (!feof())...,这与您为什么“ while(!feof(file))”总是错误的解释不符。

  • 您应该传递buffer给fwrite而不是&buffer

  • 您应该传递写入的字节数(strlen(buffer)),而不是缓冲区的大小。

  • 您说输出文件应该是二进制文件,但是您将其作为文本文件打开并向其中写入文本。您是否要将数字转换为二进制并编写二进制表示形式?

这是实现上述内容的替代方法:

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

int main(void) {
    FILE *fp;
    FILE *prob;
    int value;
    char buffer[30];

    /* Open file containing numbers */
    if ((prob = fopen("raw_numbers.txt", "r")) == NULL) {
        printf("Could not open raw_numbers.txt: %s\n", strerror(errno));
        exit(1);
    }

    /* Create output binary file */
    if ((fp = fopen("file.bin", "wb")) == NULL) {
        printf("Could not open file.bin: %s\n", strerror(errno));
        exit(1);
    }

    while (fgets(buffer, sizeof(buffer), prob) != NULL) {
        value = atoi(buffer);
        if (fwrite(&value, sizeof(value), 1, fp) != 1) {
            printf("Error writing to file.bin: %s\n", strerror(errno));
            exit(1);
        }
    }

    fclose(prob);
    fclose(fp);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Shell诊断会产生误导,但其含义是这样的:该文件my_code.exe具有一个签名(也称为幻数),该签名未被识别为可执行文件。内核无法根据其幻数(因此,错误的文件数)来确定如何运行文件。

原因是您的编译命令:gcc -pedantic -Os -c my_code.c -o my_code.exe将源文件编译my_code.c为对象格式,而不是直接链接为可执行格式。删除-c一步编译和链接的选项:

gcc -pedantic -Os my_code.c -o my_code.exe
Run Code Online (Sandbox Code Playgroud)