从文件中读取值时,垃圾附加到输出

时间:2011-02-13 21:06:24

标签: c++ file-io stream

我是C ++文件io的新手,所以前几天我决定编写一个小程序,只读取一个UTF-8编码的字符串和一个二进制文件中的配对浮点数。模式是字符串浮点数,没有额外的数据或对之间的间距。 编辑我根据几个答案修改了代码。但是,输出保持不变(“RoommateAp 0”);

string readString (ifstream* file)
{
    //Get the length of the upcoming string
    uint16_t stringSize = 0;
    file->read(reinterpret_cast<char*>(&stringSize), sizeof(char) * 2);

    //Now that we know how long buffer should be, initialize it
    char* buffer = new char[stringSize + 1];
    buffer[stringSize] = '\0';

    //Read in a number of chars equal to stringSize
    file->read(buffer, stringSize);
    //Build a string out of the data
    string result = buffer;

    delete[] buffer;
    return result;
}

float readFloat (ifstream* file)
{
    float buffer = 0;
    file->read(reinterpret_cast<char*>(&buffer), sizeof(float));
    return buffer;
}

int main()
{
    //Create new file that's open for reading
    ifstream file("movies.dat", ios::in|ios::binary);
    //Make sure the file is open before starting to read
    if (file.is_open())
    {
        while (!file.eof())
        {
            cout << readString(&file) << endl;
            cout << readFloat(&file)  << endl;
        }
        file.close();
    }
    else
    {
        cout << "Unable to open file" << endl;
    }
}

来自文件的数据样本(可读性空间):

000C 54686520526F6F6D6D617465 41700000

可以看出,前两个字节是字符串的长度(本例中为12),后跟12个字符(拼写为“The Roommate”),最后四个字节是浮点数。

当我运行此代码时,唯一发生的事情是终端挂起,我必须手动关闭它。我想这可能是因为我正在阅读文件的结尾,但我不知道为什么会这样。我做错了什么?

4 个答案:

答案 0 :(得分:5)

至少有两个问题。第一,行:

file->read(reinterpret_cast<char*>(stringSize), sizeof(char) * 2);

可能应该使用stringSize的地址:

file->read(reinterpret_cast<char*>(&stringSize), sizeof(stringSize));

第二,行:

char* buffer = new char[stringSize];

没有分配足够的内存,因为它不考虑NUL终结符。该代码应该像:

//Now that we know how long buffer should be, initialize it
char* buffer = new char[stringSize + 1];
//Read in a number of chars equal to stringSize
file->read(buffer, stringSize);
buffer[stringSize] = '\0';

最后,行:

return static_cast<string>(buffer);

从缓存中delete[]实例化后,失败到string,这将导致内存泄漏。

另请注意,std::string的UTF-8支持开箱即用。幸运的是,有solutions

答案 1 :(得分:2)

您的代码存在一些严重问题:

  1. file->read(reinterpret_cast<char*>(stringSize), sizeof(char) * 2);

    在此部分中,您将stringSize当前值转换为  一个指针。你的想法最有可能是传递地址  stringSize变量。

  2. char* buffer = new char[stringSize];

    这会分配一个字符数组,但没有人会释放它。使用 std::vector<char> buffer(stringSize);而不是记忆 管理将为您正确完成。 要获取缓冲区的地址,您可以使用&buffer[0]

  3. return static_cast<string>(buffer);

    你可能想要的是接受的字符串构造函数 指向第一个和最后一个字符的指针。换一种说法: return std::string(&buffer[0], &buffer[0]+stringSize);

答案 2 :(得分:0)

您转换为字符数组。文件中的字符串大小编号是否包含空字符的空格?如果没有,你可能会在字符数组的末尾运行并在cout write上永远循环。

答案 3 :(得分:0)

您的代码存在一些问题。

您声明字符串的大小由4个字节指定,这意味着您应该使用uint32_t而不是uint16_t。

分配字符串缓冲区时,不释放使用的内存。

string readString(std::ifstream* file)
{
    // Get the length of the upcoming string.
    // The length of the string is specified with 4 bytes: use uint32_t, not uint16_t
    uint32_t stringSize = 0;    
    file->read(reinterpret_cast<char*>(&stringSize), sizeof(uint32_t));

    // Now that we know how long buffer should be, initialize it
    char* buffer = new char[stringSize + 1];
    buffer[stringSize] = '\0'; // null terminate the string

    //Read in a number of chars equal to stringSize
    file->read(buffer, stringSize);
    string result = buffer;

    delete[] buffer;
    return result;
}