[C++] c++中二进制文件的创建与使用

二进制文件和文本文件是不同的文件类型,因此在创建等方式也是不一样的

使用文件方式见下表:

"r"(只读) 为输入打开一个文本文件

"w"(只写) 为输出打开一个文本文件

"a"(追加) 为追加打开一个文本文件

"rb"(只读) 为输入打开一个二进制文件

"wb"(只写) 为输出打开一个二进制文件

"ab"(追加) 为追加打开一个二进制文件

"r+"(读写) 为读/写打开一个文本文件

"w+"(读写) 为读/写创建一个文本文件

"a+"(读写) 为读/写打开一个文本文件

"rb+"(读写) 为读/写打开一个二进制文件

"wb+"(读写) 为读/写创建一个二进制文件

"ab+"(读写) 为读/写打开一个二进制文件

void generateBin(string filename, int npattern ,int ninput, int noutput){
        FILE* file;

        file = fopen(filename.c_str(), "w");
        if (file == NULL)
        {
                throw runtime_error("network: could not open " + string(filename) + " for writing");
        }

        fwrite(&npattern, sizeof(int), 1, file);
        fwrite(&ninput, sizeof(int), 1, file);
        fwrite(&noutput, sizeof(int), 1, file);

        float * input = new float[ninput];
        float * output = new float[noutput];

        float range = 1;

        for (int n = 0; n < npattern;n++){
                for (int i = 0; i < ninput; i++){
                        input[i] = range * ((float)rand() / RAND_MAX - 0.5);
                }
                fwrite(input,sizeof(float),ninput,file);

                for (int o = 0; o < noutput; o++){
                        output[o] = range * ((float)rand() / RAND_MAX - 0.5);
                }
                fwrite(output, sizeof(float), noutput, file);
        }

        if (fclose(file) != 0) {
                throw runtime_error("network: error on saving to " + string(filename));
        }

        delete input;
        delete output;

}

void readdata(){
        int ninput =0;
        int noutput = 0;
        int npatterns = 0;
        size_t data_read = 0;
        float* inputs = new float[ninput];
        float* targets = new float[noutput];

        string filename = "data.bin";

        FILE *file = fopen(filename.c_str(), "r");
        if (file == NULL)
                throw runtime_error("Cannot open file " + filename + " for reading");

        int ok =
                fread(&npatterns, sizeof(int), 1, file) &&
                fread(&ninput, sizeof(int), 1, file) &&
                fread(&noutput, sizeof(int), 1, file);

        cout << npatterns << " " << ninput << " " << noutput << endl;
        cout << "ninput is:" << ninput << endl;
        cout << "noutput is:" << noutput << endl;
        cout << "npatterns is:" << npatterns << endl;

        for (int i = 0; i < npatterns; i++) {
                cout << "load_patterns i:" << i << endl;
                data_read = fread(inputs, sizeof(float), ninput, file);
                cout << "need: " << ninput << " get: " << data_read << endl;
                if (data_read != ((size_t)ninput)) {
                        cout << "Wrong file format " << endl;
                        fclose(file);
                        throw runtime_error("Wrong file format");
                }
                data_read = fread(targets, sizeof(float), noutput, file);
                if (data_read != ((size_t)noutput)) {
                        cout << "Wrong file format " << endl;
                        fclose(file);
                        throw runtime_error("Wrong file format");
                }
                cout << "load_patterns i:" << i << endl;
        }
        delete inputs;
        delete targets;
        fclose(file);
}

  上面两段程序,试图创建一个二进制文件,并且向其中写入data,并且再在其中读出二进制数据。

但是运行的结果是错误的,

data_read 的数量小于ninput,原因是因为使用了文本文件的创建方式,但是确使用了二进制文件的操作。应该改为如下的代码
void generateBin(string filename, int npattern ,int ninput, int noutput){
    FILE* file;

    file = fopen(filename.c_str(), "wb");
    if (file == NULL)
    {
        throw runtime_error("network: could not open " + string(filename) + " for writing");
    }

    fwrite(&npattern, sizeof(int), 1, file);
    fwrite(&ninput, sizeof(int), 1, file);
    fwrite(&noutput, sizeof(int), 1, file);

    float * input = new float[ninput];
    float * output = new float[noutput];

    float range = 1;

    for (int n = 0; n < npattern;n++){
        for (int i = 0; i < ninput; i++){
            input[i] = range * ((float)rand() / RAND_MAX - 0.5);
        }
        fwrite(input,sizeof(float),ninput,file);

        for (int o = 0; o < noutput; o++){
            output[o] = range * ((float)rand() / RAND_MAX - 0.5);
        }
        fwrite(output, sizeof(float), noutput, file);
    }

    if (fclose(file) != 0) {
        throw runtime_error("network: error on saving to " + string(filename));
    }

    delete input;
    delete output;

}

void readdata(){
    int ninput =0;
    int noutput = 0;
    int npatterns = 0;
    size_t data_read = 0;
    float* inputs = new float[ninput];
    float* targets = new float[noutput];

    string filename = "data.bin";

    FILE *file = fopen(filename.c_str(), "rb");
    if (file == NULL)
        throw runtime_error("Cannot open file " + filename + " for reading");

    int ok =
        fread(&npatterns, sizeof(int), 1, file) &&
        fread(&ninput, sizeof(int), 1, file) &&
        fread(&noutput, sizeof(int), 1, file);

    cout << npatterns << " " << ninput << " " << noutput << endl;
    cout << "ninput is:" << ninput << endl;
    cout << "noutput is:" << noutput << endl;
    cout << "npatterns is:" << npatterns << endl;

    for (int i = 0; i < npatterns; i++) {
        cout << "load_patterns i:" << i << endl;
        data_read = fread(inputs, sizeof(float), ninput, file);
        cout << "need: " << ninput << " get: " << data_read << endl;
        if (data_read != ((size_t)ninput)) {
            cout << "Wrong file format " << endl;
            fclose(file);
            throw runtime_error("Wrong file format");
        }
        data_read = fread(targets, sizeof(float), noutput, file);
        if (data_read != ((size_t)noutput)) {
            cout << "Wrong file format " << endl;
            fclose(file);
            throw runtime_error("Wrong file format");
        }
        cout << "load_patterns i:" << i << endl;
    }
    delete inputs;
    delete targets;
    fclose(file);
}