C ++从文本文件到二进制文件

时间:2016-05-06 23:18:38

标签: c++ text-files binaryfiles

我的任务是将.txt文件[直接访问文件]中的元素复制到.bin文件[固定长度记录文件](作业)。 .txt文件包含字符串。每一行都有一个字。 我想出了下面的代码,但我不确定这是否需要,甚至是非常正确的。任何帮助都会有用! (我是C ++的新手)

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int buffer_size = 30;

class Word{
    char name[buffer_size];
public:
    void setName () // Trying to get every word from a line
    {
        string STRING;
        ifstream infile;
        infile.open ("text.txt");
        while(!infile.eof()) // To get you all the lines.
        {
            getline(infile,STRING); // Saves the line in STRING.
        }
        infile.close();
    }
};


void write_record()
{
    ofstream outFile;
    outFile.open("binFILE.bin", ios::binary | ios::app);
    Word obj;
    obj.setName();
    outFile.write((char*)&obj, sizeof(obj));
    outFile.close();
}


int main()
{
    write_record();
    return 0;
}

新方法:

class Word
{
char name[buffer_size];
public:
    Word(string = "");
    void setName ( string );
    string getName() const;
};

    void readWriteToFile(){
        // Read .txt file content and write into .bin file
        string temp;
        Word object;
        ofstream outFile("out.dat", ios::binary);
        fstream fin ("text.txt", ios::in);
        getline(fin, temp);
        while(fin)
        {
            object.setName(temp);
            outFile.write( reinterpret_cast< const char* >( &object ),sizeof(Word) );
            getline(fin, temp);
        }
        fin.close();
        outFile.close();
}

int main()
{
readWriteToFile();


return 0;
}
Word::Word(string nameValue)
{
setName(nameValue);
}
void Word::setName( string nameString )
{
// Max 30 char copy
const char *nameValue = nameString.data();
int len = strlen(nameValue);
len = ( len < 31 ? len : 30);
strncpy(name, nameValue, len);
name[len] = '\0';
}
string Word::getName() const
{

返回姓名;     }

1 个答案:

答案 0 :(得分:0)

快速评论并逐步完成

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

在学习期间避免using namespace std;。它可能导致一些非常讨厌,难以确定的错误,因为您的函数可能会被标准库中具有相同名称的函数静默替换。

const int buffer_size = 30;

class Word
{
    char name[buffer_size];

既然看起来你可以使用std::string,为什么不在这里使用呢?

public:
    void setName() // Trying to get every word from a line

显然应该// Trying to get every word from a line

的函数的名字真的很糟糕
    {
        string STRING;
        ifstream infile;
        infile.open("text.txt");
        while (!infile.eof()) // To get you all the lines.
        {
            getline(infile, STRING); // Saves the line in STRING.
        }

这里几乎没有错。一个是史诗Why is iostream::eof inside a loop condition considered wrong?

接下来是代码读取每一行时,它不会对该行执行任何操作。 STRING永远不会存储在任何地方。

最后,在一个听起来应该包含和管理单个单词的类中,它会读取文件中的所有单词。可能存在将此函数转换为静态工厂的情况,该工厂会生成std::vector Words

        infile.close();
    }
};

void write_record()
{
    ofstream outFile;
    outFile.open("binFILE.bin", ios::binary | ios::app);

ios::app将添加到现有文件中。这听起来不像作业说明中描述的那样。

    Word obj;
    obj.setName();

我们已经掩盖了Word课程的失败。

    outFile.write((char*) &obj, sizeof(obj));

在不定义数据协议或使用任何序列化的情况下将对象喷射到流中是危险的。它使文件不可移植。您会发现其中一些显着的类vectorstring不包含其数据。将字符串写入文件可能只会带来一个计数和一个在加载文件时几乎肯定无效的地址。

在这种情况下,所有对象包含的是一个字符数组,应该干净地写入文件,但它总是写出30个字节,这可能不是你想要的。

    outFile.close();
}

int main()
{
    write_record();
    return 0;
}

由于这是作业,我不是为你写这个吸盘,但这里有一些建议:

Read file line by line将帮助您开始使用文件阅读器。您的情况更简单,因为每行只有一个单词。你的老师可能会抛出一个曲线球,并在线上添加更多东西,所以你可能想测试一下。

将文件中的文字读入std::vectorvector会让你的工作变得如此简单,以至于你可能有时间做其他功课。

一个非常简单的实现是:

std::vector<std::string> words;
while (getline(infile, STRING)) // To get you all the lines.
{
    words.push_back(STRING);
}

以二进制形式写回文件,I suggest going Pascal style.首先以二进制形式写入字符串的长度。 Use a known, fixed width unsigned integer(没有负字符串)和watch out for endian。写入长度后,只写入需要写入的字符数。

忽略endian,你应该有这样的东西:

uint32_t length = word.length(); // length will always be 32 bits
out.write((char*)&length, sizeof(length));
out.write(word.c_str(), length);

编写完编写器后,编写一个读取器函数,以便测试编写器是否正常工作。总是测试你的代码,我建议你不要写任何东西,直到你知道你将如何测试它。经常从测试方面参加一个程序会在他们有机会开始之前发现问题。