我們的目標是從一個二進制檔案中讀取16位有符號整數。首先,我將檔案作為ifstream打開,然后我想使用istream_iterator和copy演算法將每個數字復制到一個向量。 我不明白這個片段有什么問題:
int main(int argc, char *argv[]) {
std::string filename("test.bin"/span>)。
std::ifstream is(filename)。
if (! is) {
std::cerr << "打開輸入檔案時出現錯誤
"。
return EXIT_FAILURE。
}
std::noskipws(is)。
std::vector<int16_t> v;
std::copy(
std::istream_iterator<int16_t>(is)。
std::istream_iterator<int16_t>()。
std::back_inserter(v)
);
//v仍然是空的。
}
這段代碼沒有產生錯誤,但是在呼叫std::copy之后,向量仍然為空。因為我是以標準輸入模式("文本 "模式)打開檔案的,我希望istream_iterator能夠作業,即使檔案是二進制的。當然,關于這個類的行為,我還漏掉了一些東西。
uj5u.com熱心網友回復:
首先,要用ifstream讀取二進制檔案,你需要以二進制模式打開檔案,而不是文本模式(默認)。否則,讀取操作可能會誤解換行位元組,并在平臺編碼之間進行轉換(即CRLF->LF,或反之),從而破壞你的二進制資料。
第二,istream_iterator使用operator>>,它默認讀取和決議格式化文本,這不是你在讀取二進制檔案時想要的。你需要使用istream::read()代替。然而,并沒有相應的迭代器包裝器(但如果需要,你可以自己寫)。
嘗試這樣做:
int main(int argc, char *argv[]) {
std::string filename = "test.bin"/span>;
std::ifstream is(filename, std::ifstream:binary);
if (! is) {
std::cerr << "打開輸入檔案時出現錯誤
"。
return EXIT_FAILURE。
}
std::vector<int16_t> vec;
int16_t值。
while (is. read(reinterpret_cast<char*>(&value), sizeof(value)) {
//交換value的endian,如果需要的話...
vec.push_back(value)。
}
//根據需要使用vec...。
return 0;
}
這就是說,如果你真的想對二進制檔案使用istream_iterator,那么你必須寫一個自定義的類/結構來包裝int16_t,然后為該型別定義一個operator>>來呼叫read(),例如:
struct myInt16_t {
int16_t值。
operator int16_t() const{ return value;}; };> int16_t value; const
};
std::istream& operator>>(std::istream &is, myInt16_t &v) {
if (is.read(reinterpret_cast<char*> (& v. value), sizeof(v.value))) {
//交換v.value的endian,如果需要的話...。
}
return 是。
}
int main(int argc, char *argv[]) {
std::string filename = "test.bin"/span>;
std::ifstream is(filename, std::ifstream:binary);
if (! is) {
std::cerr << "打開輸入檔案時出現錯誤
"。
return EXIT_FAILURE。
}
std::noskipws(is)。
std::vector<int16_t> vec;
std::copy(
std::istream_iterator<myInt16_t>(is)。
std::istream_iterator<myInt16_t>()。
std::back_inserter(vec)
);
//根據需要使用vec...。
return 0;
}
uj5u.com熱心網友回復:
因為我是以標準輸入模式("文本 "模式)打開檔案的,所以我希望istream_iterator能夠作業,即使檔案是二進制的。
你在概念上走錯了路。由于檔案 "是二進制的"1,你不應該期望istream_iterator作業即使檔案是以 "文本模式"2打開。檔案的格式決定了你能用它做什么;沒有任何工具能從檔案中讀取 "格式化為人類可讀的文本的數字",除非該檔案實際上打算以這種方式被讀取。你的檔案應該是以 "成對的位元組,每個位元組代表一個16位的數字值 "的方式來讀取的,所以你需要與這種格式兼容的工具。檔案mode只是拼圖中的一小塊。
為了對檔案進行有意義的迭代,您需要以二進制模式打開它(以避免在 Windows 平臺上出現損壞)并且使用一個能夠以您想要的方式解釋二進制資料的工具。你還需要確保你對資料的思考是正確的。試圖使用像noskipws這樣的東西是沒有意義的,因為資料沒有空白的概念,因為它并不代表文本。
嚴格來說,這并不意味著什么;但通常情況下,說一個檔案 "是二進制的 "表明檔案內容不是為了讓人閱讀,而且數字值是按照它們在計算機記憶體中的情況來表示的,即直接以256為基數,而不是使用位元組來表示文本,反過來用阿拉伯數字、
.符號等來表示一個數字。"以文本模式 "打開一個檔案的含義取決于你所使用的語言和平臺。在許多語言中(包括C和C ),它在Windows上的影響很小(基本上只是就地翻譯CR-LF序列),而在類似Linux的平臺上則沒有任何影響(至少在我最后一次檢查時)。在一些語言中(比如Python 3.x),它自動帶來了將位元組轉換為代表實際文本的物件的機制,實際上使用了一種編碼,而不是假裝位元組 "是字符"(它們不是)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/314147.html
標籤:
上一篇:兩個洗掉函式的宣告之間的區別
