简体   繁体   English

在C ++中读写二进制文件

[英]Reading and writing to binary file in C++

I need to make a file that contains "name" which is a string -array of char- and "data" which is array of bytes -array of char in C++- but the first problem I faced is how to separate the "name" from the "data"? 我需要制作一个包含“名称”的文件,该文件是一个字符串-char数组-和“数据”这是字节数组-在C ++中是char数组-但是我遇到的第一个问题是如何分隔“名称”从“数据”? newline character could work in this case (assuming that I don't have "\\n" in the name) but I could have special characters in the "data" part so there's no way to know when it ends so I'm putting an int value in the file before the data which has the size of the "data"! 在这种情况下,可以使用换行符(假设名称中没有“ \\ n”),但是在“数据”部分中可以包含特殊字符,因此无法知道何时结束,因此我将文件中的int值,该数据在具有“数据”大小的数据之前! I tried to do this with code as follow: 我尝试使用以下代码来做到这一点:

if((fp = fopen("file.bin","wb")) == NULL)
{
    return false;
}
char buffer[] = "first data\n";
fwrite( buffer ,1,sizeof(buffer),fp );
int number[1];
number[0]=10;
fwrite( number ,1,1, fp );
char data[] = "1234567890";
fwrite( data , 1, number[0], fp );
fclose(fp);

but I didn't know if the "int" part was right, so I tried many other codes including this one: 但我不知道“ int”部分是否正确,因此我尝试了许多其他代码,包括此代码:

char buffer[] = "first data\n";
fwrite( buffer ,1,sizeof(buffer),fp );
int size=10;
fwrite( &size ,sizeof size,1, fp );
char data[] = "1234567890";
fwrite( data , 1, number[0], fp );

I see 4 "NULL" characters in the file when I open it instead of seeing an integer. 当我打开文件时,我看到的是4个“ NULL”字符,而不是整数。 Is that normal? 那是正常的吗? The other problem I'm facing is reading that again from the file! 我面临的另一个问题是从文件中再次读取该信息! The code I tried to read didn't work at all :( I tried it with "fread" but I'm not sure if I should use "fseek" with it or it just read the other character after it. 我尝试读取的代码根本不起作用:(我用“ fread”尝试过,但是我不确定是否应该在其中使用“ fseek”或仅读取其后的另一个字符。

I thought of using a class as following and then writing and reading it back: 我想到使用以下类,然后编写并读回它:

class Sign
{
public:
char* name;
int size;
char* data;
};

but that was not an easy thing in C++ !! 但这在C ++中并非易事!

I also tried the following: 我还尝试了以下方法:

void saveData(char* filename) {

    fstream filestr;
    int n;
    n=10;
    char* data= "1234567890";

    filestr.open (filename, fstream::out | fstream::binary);
    for (int j = 0; j<5 ; j++)
    {
       filestr << n;

       for (int i = 0; i < n; i++) {
            filestr << data[i];
       }
    }
    filestr.close();
}

void readData(char* filename) {
    fstream filestr;
    int n =0;

    filestr.open (filename, fstream::in | fstream::binary);
    int m =0;
    //while(!filestr.eof())
    while(m<5)
    {
        filestr >> n;

        char *data = new char[n];
        for (int i = 0; i < n; i++) {
            filestr >> data[i];
        }
        printf("data is %s\n",data);
        m++;
    }
    filestr.close();
}

But the reading didn't work either. 但是阅读也不起作用。

On reading I'm getting strange characters. 在阅读时,我得到了奇怪的人物。


So far the code that works for me is this: 到目前为止,对我有用的代码是这样的:

void saveData(char* filename) {
    fstream filestr;
    char * name = "first data\n";
    int n;
    n=10;
    char* data= "asdfghjkl;";

    filestr.open (filename, fstream::out | fstream::binary);
    for (int j = 0; j<5 ; j++)
    {
        filestr << name;
        filestr << strlen(data);
        filestr << data;
    }
    filestr.close();
}


void readData(char* filename) {
    fstream filestr;
    int n =0;

    filestr.open (filename, fstream::in | fstream::binary);
    while(!filestr.eof())
    {
        string name;
        getline(filestr,name,'\n');
        printf("name is %s\n",name.c_str());

        filestr >> n;

        char *data = new char[n];
        for (int i = 0; i < n; i++) {
            filestr >> data[i];
        }
        printf("n is%d\ndata is %s\n",n,data);
    }
    filestr.close();
}

but the problems in reading are: 但是阅读中的问题是:

1- (I don't think it's a real problem) it prints other characters in addition to the actual data. 1-(我认为这不是真正的问题),除了实际数据外,它还打印其他字符。 2- on readData function I get the output 6 times (in the last time I get every field as an empty field) while I have written only 5 times! 2-关于readData函数,我得到了6次输出(最后一次获得每个字段为空字段),而我只写了5次! Anyone knows why is that? 有人知道为什么吗? is that related to while(!filestr.eof()) ?? while(!filestr.eof())吗?

Thanks for help 感谢帮助

First, your writing / reading in binary format should work like this (here read_num would contain 10 after this reading sequence). 首先,您以二进制格式进行的写入/读取应该像这样工作(在此读取序列之后, read_num将包含10 )。

   FILE* fp = fopen("file.bin", "wb");
   int num = 10;
   fwrite(&num, sizeof(int), 1, fp);
   fclose(fp);

   FILE* fp2 = fopen("file.bin", "rb");
   int read_num;
   fread(&read_num, sizeof(int), 1, fp2);
   fclose(fp2);

Also to mention, this way of writing is not the C++ way, but is the C way. 另外要提一下,这种书写方式不是C ++方式,而是C方式。 C++ way of file operations means streams, see the following sample: C ++文件操作方式表示流,请参见以下示例:

#include <fstream>
#include <string>

struct data_structure {
   std::string name;
   std::string description;
   int number;

   void save(const std::string& filename) {
      std::ofstream file(filename.c_str());
      file << name.c_str() << std::endl
           << description.c_str() << std::endl
           << number;
   }
   void load(const std::string& filename) {
      std::ifstream file(filename.c_str());

      getline(file, name);
      getline(file, description);
      file >> number;
   }
};

int main() {
   data_structure d, loaded_d;
   d.name = "Name";
   d.description = "Description";
   d.number = 5;

   d.save("file.out");
   loaded_d.load("file.out");

   return 0;
}

Well, a few issues with your code: 好吧,您的代码存在一些问题:

fwrite( buffer ,1,sizeof(buffer),fp );

The function is defined as this: 该函数的定义如下:

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

So you're sending the information in buffer, saying it has a size of 1, and count of sizeof(buffer). 因此,您正在缓冲区中发送信息,说它的大小为1,并且计数为sizeof(buffer)。 That might work for some things, but is just generally backwards. 这可能对某些事情有用,但通常只是倒退。 Try using: 尝试使用:

fwrite(buffer, sizeof(char), strlen(buffer), fp);

That's both character-width independent and has no constant values you need to worry about (it will work for basically any string). 这既与字符宽度无关,也没有常量值,您无需担心(它几乎适用于任何字符串)。

Another minor thing in this: 另外一件小事:

 int number[1];

You have a single integer, so you need only use: 您只有一个整数,因此只需要使用:

 int number;

If you run into errors with fwrite after changing it, use this call: 如果更改后在fwrite遇到错误,请使用以下调用:

fwrite( &number, sizeof(int), 1, fp);

That will write the value of one integer to the file. 这会将一个整数值写入文件。

After you fix that up, see if your code works. 解决此问题后,请查看您的代码是否有效。 It will certainly be easier to troubleshoot with those calls corrected. 通过更正这些呼叫,当然可以更轻松地进行故障排除。 :) :)

Also, if you're planning on using field lengths (written as ints into the file), you're going to want to set up some kind of system to read the length, then data, and you should probably have a length for each field. 另外,如果您打算使用字段长度(以int形式写入文件),则需要设置某种系统来读取长度,然后读取数据,并且每个长度都应该有一个长度领域。 Using a class is definitely the easiest way to handle that. 使用类绝对是处理该问题的最简单方法。

Edit: You may want to use a struct and function instead of a class, or you could use a class with methods. 编辑:您可能想使用结构和函数而不是类,或者可以将类与方法一起使用。 It doesn't really matter, both are pretty simple. 并不重要,两者都很简单。 Struct/func: 结构/ FUNC:

struct Record
{
    std::string name, data;
};

void writeRecord(Record thisRecord, std::string filename, size_t offset)
{
    if ( ( fp = fopen(filename.c_str(), "wb") ) == NULL ) { return NULL; }

    fwrite( thisRecord.size(), sizeof(unsigned int), 1, fp); // assuming size() return uint
    fwrite( thisRecord.name.c_str(), sizeof(char), name.size(), fp);

    // repeat for data or other fields
    fclose(fp);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM