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

时间:2010-05-01 15:52:16

标签: c++ file binaryfiles

我需要创建一个包含“name”的文件,这是一个字符串-charay的char-和“data”,它是字节数组--C ++中的char数组 - 但我遇到的第一个问题是如何分离“数据”中的“名称”?换行符可以在这种情况下工作(假设我的名字中没有“\ n”)但我可以在“数据”部分中有特殊字符,所以没有办法知道它何时结束所以我放了一个在具有“数据”大小的数据之前的文件中的int值! 我尝试使用以下代码执行此操作:

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);

但我不知道“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 );

当我打开它而不是看到整数时,我在文件中看到4个“NULL”字符。这是正常的吗? 我面临的另一个问题是从文件中再次阅读!我试图阅读的代码根本不起作用:(我用“fread”尝试了它但是我不确定我是否应该使用“fseek”或它只是阅读其后的其他字符。

我想过使用一个类如下,然后写回来读它:

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

但这在C ++中并不容易!

我也尝试了以下内容:

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();
}

但阅读也不起作用。

在阅读时,我会变得很奇怪。


到目前为止,适用于我的代码是:

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();
}

但阅读中的问题是:

1-(我不认为这是一个真正的问题)除了实际数据外,它还会打印其他字符。 2- readData函数我得到输出 6 次(在上一次我将每个字段作为空字段),而我只写了 5 次!谁知道为什么会这样?是与while(!filestr.eof()) ??

有关

感谢您的帮助

2 个答案:

答案 0 :(得分:3)

首先,您的二进制格式的写作/阅读应该像这样工作(此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);

另外,这种写法不是C ++方式,而是C方式。 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;
}

答案 1 :(得分:0)

嗯,您的代码存在一些问题:

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

该功能定义如下:

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

所以你在缓冲区中发送信息,说它的大小为1,sizeof(缓冲区)的数量。这可能适用于某些事情,但通常只是倒退。尝试使用:

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

这两个字符宽度无关,并且没有您需要担心的常量值(它基本上适用于任何字符串)。

另一个小问题:

 int number[1];

您有一个整数,因此您只需使用:

 int number;

如果您在更改后遇到fwrite错误,请使用此调用:

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

这会将一个整数的值写入文件。

修好后,查看您的代码是否有效。通过纠正这些调用来解决问题肯定会更容易。 :)

另外,如果你打算使用字段长度(写入文件中的int),你会想要设置某种系统来读取长度,然后是数据,你应该有一个每个领域的长度。使用类绝对是处理它的最简单方法。

修改 您可能希望使用结构和函数而不是类,或者您可以使用带有方法的类。这并不重要,两者都很简单。结构/ 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);
}