簡體   English   中英

從文件讀取值時附加到輸出的垃圾

[英]Garbage Appended to Output When Reading Values from a File

我是C ++文件io的新手,所以前幾天,我決定編寫一個小程序,該程序僅從二進制文件讀取UTF-8編碼的字符串和成對的float。 該模式是字符串浮動的,在對之間沒有額外的數據或間隔。 編輯我已經根據幾個答案修改了代碼。 但是,輸出保持不變(“ The 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),后跟十二個字符(拼寫為“室友”),最后四個字節是浮點數。

當我運行此代碼時,唯一發生的是終端掛起,我必須手動關閉它。 我認為可能是因為我正在閱讀文件末尾的內容,但我不知道為什么會發生這種情況。 我做錯了什么?

至少有兩個問題。 一,行:

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

實例化緩沖區中的string后,無法delete[]緩沖區,這將導致內存泄漏。

還要注意, std::string的UTF-8支持非常差。 幸運的是,有解決方案

您的代碼有一些嚴重的問題:

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

您強制轉換為字符數組。 文件中的字符串大小數字是否包含空字符的空間? 否則,您可能正在運行一個字符數組的末尾,並在cout寫入中永遠循環。

您的代碼存在一些問題。

您聲明該字符串的大小由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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM