我正在尝试读取和处理多个不同编码的文件。我应该只为此使用 STL。假设我们有iso-8859-15和UTF-8文件。
在这个SO 答案中,它指出:
简而言之,对您来说更有趣的部分:
std::stream
(stringstream
,fstream
,cin
,cout
) 有一个内部语言环境对象,它与创建流对象时的全局 C++ 语言环境的值相匹配。正如std::in
在调用 main 中的代码很久之前创建的那样,它很可能具有经典的 C 语言环境,无论您之后做什么。- 您可以通过调用来确保 std::stream 对象具有所需的语言环境
std::stream::imbue(std::locale(your_favorite_locale))
。
问题在于,在这两种类型中,只有与首先创建的语言环境匹配的文件才能被正确处理。例如,如果locale_DE_ISO885915
在前面, 则未正确附加在其中的locale_DE_UTF8
文件,当我将它们取出时,我只看到文件中的几行。UTF-8
string s
cout
void processFiles() {
//setup locales for file decoding
std::locale locale_DE_ISO885915("de_DE.iso885915@euro");
std::locale locale_DE_UTF8("de_DE.UTF-8");
//std::locale::global(locale_DE_ISO885915);
//std::cout.imbue(std::locale());
const std::ctype<wchar_t>& facet_DE_ISO885915 = std::use_facet<std::ctype<wchar_t>>(locale_DE_ISO885915);
//std::locale::global(locale_DE_UTF8);
//std::cout.imbue(std::locale());
const std::ctype<wchar_t>& facet_DE_UTF8 = std::use_facet<std::ctype<wchar_t>>(locale_DE_UTF8);
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string currFile, fileStr;
std::wifstream inFile;
std::wstring s;
for (std::vector<std::string>::const_iterator fci = files.begin(); fci != files.end(); ++fci) {
currFile = *fci;
//check file and set locale
if (currFile.find("-8.txt") != std::string::npos) {
std::locale::global(locale_DE_ISO885915);
std::cout.imbue(locale_DE_ISO885915);
}
else {
std::locale::global(locale_DE_UTF8);
std::cout.imbue(locale_DE_UTF8);
}
inFile.open(path + currFile, std::ios_base::binary);
if (!inFile) {
//TODO specific file report
std::cerr << "Failed to open file " << *fci << std::endl;
exit(1);
}
s.clear();
//read file content
std::wstring line;
while( (inFile.good()) && std::getline(inFile, line) ) {
s.append(line + L"\n");
}
inFile.close();
//remove punctuation, numbers, tolower...
for (unsigned int i = 0; i < s.length(); ++i) {
if (ispunct(s[i]) || isdigit(s[i]))
s[i] = L' ';
}
if (currFile.find("-8.txt") != std::string::npos) {
facet_DE_ISO885915.tolower(&s[0], &s[0] + s.size());
}
else {
facet_DE_UTF8.tolower(&s[0], &s[0] + s.size());
}
fileStr = converter.to_bytes(s);
std::cout << fileStr << std::endl;
std::cout << currFile << std::endl;
std::cout << fileStr.size() << std::endl;
std::cout << std::setlocale(LC_ALL, NULL) << std::endl;
std::cout << "========================================================================================" << std::endl;
// Process...
}
return;
}
正如您在代码中看到的那样,我尝试过global
但locale local variables
无济于事。
此外,在如何使用 std::imbue 为 std::wcout 设置语言环境?所以回答它说:
所以看起来确实有一个底层 C 库机制,应该首先使用 setlocale 启用,以允许 imbue 转换正常工作。
这种“晦涩”的机制是这里的问题吗?
处理文件时是否可以在两种语言环境之间交替?我应该灌输什么(,,cout
?)以及如何灌输?ifstream
getline
有什么建议么?
PS:为什么和locale相关的一切都这么乱?:|