【问题标题】:Writing to a binary file from a struct part of a linked list从链表的结构部分写入二进制文件
【发布时间】:2012-04-12 03:38:26
【问题描述】:

我正在尝试了解如何正确地将数据正确写入二进制文件。正在写入数据,但是当回读以进行测试时,很明显我没有正确写入。数据读取/写入如下。

Unsigned Char 告诉下一个字符串有多长,然后写入一个字符串,然后写入一个整数 ID。 (或长度 studentname student_id )。以下是将数据保存到文件的 printList 函数。

void printList(struct node * nptr, string filename){
  ofstream myfile;
  myfile.open( filename.c_str(), ios::binary );

  while(nptr){

  myfile.write( (char*) &nptr->data.len, sizeof( unsigned char ) );
  myfile.write( (char*) nptr->data.name, len * sizeof(char) );
  myfile.write( (char*) &nptr->data.id, sizeof(int) );

 //myfile.write( (const char*) &nptr->data, sizeof( Student ) );

 nptr = nptr->next;
}

myfile.close();

}

这里是数据存储在链接列表中的学生结构:

struct node{
Student data;
struct node* next;
};

//=== Student struct===//
 struct Student{
    unsigned char len;
char* name;
int id;
};
//====================//

这是我为读取二进制文件而编写的 loadbin 文件,我又搞砸了,我已经阅读并观看了大量关于此的教程。我真的很难过。

unsigned char len;
char* name;
int id;

int main( int argc, char* argv[] )
{
    if( argc > 1 )
    {
        ifstream f( argv[1] , ios::binary);

        while( !f.eof() )
        {
            f.read( (char*) &len , sizeof( unsigned char ) );

            if( f.eof() )
                break;

        name = new char[len+1];
        name[len+1] = '\0';

        f.read( (char*) name , len * sizeof( char ) );
        f.read( (char*) &id , sizeof( int ) );

        cout << (int)len << " " << name << " " << id 
                                            << "\n";
        }
    }

   else
        cout << "\nToo few arguments.\n";

}

更多信息,我无法更改文件被重新读入的方式。修复必须来自我写作的时候。我只是把它包括在内,以防万一。

【问题讨论】:

  • 你有文件的十六进制转储吗?您能提供一个片段以及用于编写它的原始测试数据吗?
  • 您最好能够更改文件被读回的方式......它完全被破坏了。正确的习惯用法是首先尝试读取,然后使用 fail、eof 和/或 gcount(或隐式转换为 bool)评估成功。例如,while (f.read(...)) { name = ...; if (f.read(...) && f.read(...)) cout ... }. Also, name[len+1] = '\0'` 写入 PAST 缓冲区的末尾 - 未定义的行为- 应该是name[len]。另外,if (ofstream of(..., ...)) { for (; nptr; nptr = nptr-&gt;next) if (!(f.write(...) &amp;&amp; f.write(...) ...)) { cerr &lt;&lt; ...; break; }

标签: c++ struct binaryfiles writing


【解决方案1】:

开始,我什至不确定这是否应该编译,除非你有一个 len 变量在某处浮动,例如在你的最后一个代码段中:

myfile.write( (char*) nptr->data.name, len * sizeof(char) ); // len, what len?

由于sizeof(char) 始终为 1,并且我更喜欢显式表达式,因此我将三个输出行重写为:

myfile.write ((const char *)(&(nptr->data.len)), 1);
myfile.write ((const char *)(nptr->data.name), nptr->data.len);
myfile.write ((const char *)(&(nptr->data.id)), sizeof(int));

一个完整的程序展示了如何使用它,它非常相似,它会有所帮助,但又足够不同,以至于你不能把它当作你自己的工作提交:-)

#include <iostream>
#include <fstream>

struct Student {
    unsigned char len;
    char *name;
    int id;
};

struct node {
    Student data;
    struct node *next;
};

int main (void) {
    // Create dummy list, two nodes.

    node *temp = new node();
    temp->data.len = 6;
    temp->data.name = (char *)"diablo";
    temp->data.id = 2;
    temp->next = NULL;

    node *shortList = new node();
    shortList->data.len = 3;
    shortList->data.name = (char *)"pax";
    shortList->data.id = 1;
    shortList->next = temp;

    // Write it out.

    std::ofstream myfile;
    myfile.open ("xyzzy.bin", std::ios::binary);
    node *curr = shortList;
    while (curr != NULL) {
        myfile.write ((const char *)(&(curr->data.len)), 1);
        myfile.write ((const char *)(curr->data.name), curr->data.len);
        myfile.write ((const char *)(&(curr->data.id)), sizeof(int));
        curr = curr->next;
    }
    myfile.close ();

    return 0;
}

如果你运行那个程序然后做一个十六进制转储,你会得到:

addr  +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f  0123456789abcdef
----  -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  ----------------
0000  03 70 61 78 01 00 00 00 06 64 69 61 62 6c 6f 02  .pax.....diablo.
0010  00 00 00                                         ...
0013

我认为符合您想要的格式。

【讨论】:

  • 谢谢!我明白我现在做错了什么。今天课上没有解释得那么好,就冲到了最后。它是 write 函数的第二个参数。我现在明白了。再次感谢。干杯。
【解决方案2】:

如果没有文件内容的线索,很难调试,但尽量确保事情绝对清楚。

而不是

  myfile.write( (char*) &nptr->data.len, sizeof( unsigned char ) );
  myfile.write( (char*) nptr->data.name, len * sizeof(char) );
  myfile.write( (char*) &nptr->data.id, sizeof(int) );

写起来不容易出错(我挤出了空格以保持在行长之内):

  myfile.write((char*)&nptr->data.len, sizeof(nptr->data.len) );
  myfile.write((char*)nptr->data.name, nptr->data.len*sizeof(nptr->data.name[0]));
  myfile.write((char*)&nptr->data.id, sizeof(nptr->data.id) );

并在读回数据时使用类似的表达式来解包数据。对变量使用 sizeof 比使用类型名称更健壮。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    • 1970-01-01
    • 2019-10-01
    相关资源
    最近更新 更多