繁体   English   中英

如何在c ++中处理ifstream,cout等的多个语言环境

[英]How to handle multiple locales for ifstream, cout, etc, in c++

我正在尝试读取和处理不同编码的多个文件。 我应该只为此使用STL。 假设我们有iso-8859-15UTF-8文件。

这个 SO答案中,它指出:

简而言之,对你来说更有趣的部分:

  1. std::streamstringstreamfstreamcincout )有一个内部locale-object,它与创建流对象时的全局C ++语言环境的值相匹配。 由于std::in是在调用main中的代码之前很久就创建的,因此无论你以后做什么,它都很可能是经典的C语言环境。
  2. 您可以通过调用std::stream::imbue(std::locale(your_favorite_locale))来确保std :: stream对象具有所需的语言环境。

问题是,从这两种类型中,只有与首先创建的语言环境匹配的文件才能正确处理。 例如,如果locale_DE_ISO885915locale_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;
}

正如您在代码中看到的那样,我尝试使用globallocale local variables但无济于事。

另外,在如何使用std :: imbue设置std :: wcout的语言环境? 所以回答它说:

所以看起来真的有一个底层的C库机制应该首先使用setlocale启用,以允许imbue转换正常工作。

这个“模糊”的机制在这里是一个问题吗?

处理文件时是否可以在两个语言环境之间切换? 我应该灌输什么( coutifstreamgetline ?)以及如何?

有什么建议?

PS:为什么与locale相关的一切都如此混乱? :|

这在我的Linux机器上按预期工作,但在我的Windows机器上不适用于Cygwin(两个机器上的可用语言环境显然相同,但是std::locale::locale只是因为每个可以想象的语言环境字符串而失败)。

#include <iostream>
#include <fstream>
#include <locale>
#include <string>

void printFile(const char* name, const char* loc)
{
  try {
    std::wifstream inFile;
    inFile.imbue(std::locale(loc));
    inFile.open(name);
    std::wstring line;
    while (getline(inFile, line))
      std::wcout << line << '\n';
  } catch (std::exception& e) {
    std::cerr << e.what() << std::endl;
  }
}

int main()
{
  std::locale::global(std::locale("en_US.utf8"));

  printFile ("gtext-u8.txt", "de_DE.utf8");       // utf-8 text: grüßen
  printFile ("gtext-legacy.txt", "de_DE@euro");   // iso8859-15 text: grüßen
}

输出:

grüßen
grüßen

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM