簡體   English   中英

如何在Linux上用std :: ifstream讀取文件中的非ASCII行?

[英]How to read non-ASCII lines from file with std::ifstream on Linux?

我試圖讀取純文本文件。 在我的情況下,我需要讀取每行的行,並處理該信息。 我知道C ++有閱讀wchars的功能。 我嘗試了以下方法:

#include <fstream>
#include <iostream>

int main() {
    std::wfstream file("file");       // aaaàaaa
    std::wstring str;
    std::getline(file, str);
    std::wcout << str << std::endl;   // aaa
}

但正如你所看到的,它沒有讀完整行。 讀取“à”時會停止,這是非ASCII。 我該如何解決?

您需要了解編碼的一些基本概念。 我建議閱讀這篇文章: 絕對最低每個軟件開發人員絕對必須知道Unicode和字符集 基本上你不能假定每個字節是一個字母,每一個字母適合在一個char 此外,系統必須知道如何從文件中的字節序列中提取字母。

假設您的文件是以UTF-8編碼的,這很可能是因為您使用的是Linux。 我假設您的終端也支持它。 如果您直接使用std::string讀取,使用chars,您將擁有一切正常工作。 看:

// olá
#include <iostream>
#include <fstream>
int main() {
    std::fstream file("test.cpp");
    std::string str;
    std::getline(file, str);
    std::cout << str << std::endl;
}

輸出是你所期望的,但這不是真的正確。 看看發生了什么:文件以utf-8編碼。 這意味着第一行是這個字節序列:

/  /     o   l       á
47 47 32 111 108 195 161

請注意, á用兩個字節編碼 如果你詢問字符串的大小( str.size() ),你的確會得到錯誤的值: 7 發生這種情況是因為字符串認為每個字節都是char。 當您將其發送到std::cout ,該字符串將被提供給終端進行打印。 神奇的部分:終端默認使用utf-8。 所以它只是假設字符串是utf-8並正確打印6個字符。

你看它有效,但它不是真的。 嘗試對數據進行任何字符串操作,您可能會破壞utf-8編碼,永遠無法再次打印!

我們去找wstring 它們使用wchar_t存儲每個字母,在Linux上,它具有4個字節。 這足以容納任何可能的unicode字符。 但它不會直接起作用,因為默認情況下C ++使用"C"語言環境。 區域設置是如何處理系統的各個方面的規范,例如“如何打印日期”或“如何格式化貨幣值”或甚至“如何解碼文本”。 最后一個因素很重要,默認的"C"編碼說:“假設一切都是ASCII”。 當它正在讀取文件並嘗試解碼非ASCII字節時,它只是無聲地失敗。

更正很簡單:使用UTF-8語言環境。 看:

// olá
#include <iostream>
#include <fstream>
#include <locale>

int main() {
    std::ios::sync_with_stdio(false);

    std::locale loc("en_US.UTF-8"); // You can also use "" for the default system locale
    std::wcout.imbue(loc); // Use it for output

    std::wfstream file("test.cpp");
    file.imbue(loc); // Use it for file input
    std::wstring str;
    std::getline(file, str); // str.size() will be 6
    std::wcout << str << std::endl;
}

你可能會問std::ios::sync_with_stdio(false); 手段。 這是必需的,因為默認情況下C ++流與C流保持同步。 這很好,因為您可以在同一程序中同時使用coutprintf 我們必須禁用它,因為C流將破壞utf-8編碼並將在輸出上產生垃圾。

暫無
暫無

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

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