[英]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支持非常差。 幸運的是,有解決方案 。
您的代碼有一些嚴重的問題:
file->read(reinterpret_cast<char*>(stringSize), sizeof(char) * 2);
在這一部分中,您正在將stringSize
的當前值轉換為指針。 您的想法很可能是傳遞stringSize
變量的地址。
char* buffer = new char[stringSize];
這會分配一個字符數組,但是沒有人會釋放它。 使用std::vector<char> buffer(stringSize);
而是可以為您正確進行內存管理。 要獲取緩沖區的地址,可以使用&buffer[0]
。
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.