C ++要正确使用cout wcout ifstream来读取带有重音符号的文本文件

问题描述

我想在Ubuntu 20.04上读取文件txt编码的UTF8。

我在wcout cout和ifstream中添加了语言环境fr_FR.UTF-8。

我当时想添加语言环境就足够了。

输出显示以下内容

enter image description here

这是我的代码

...
#include <iostream>
#include <fstream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <string>
#include <locale>
#include <codecvt>
    
int main(int argc,char** argv){
    
    int nbreLigne;
    std::vector<std::wstring> dico;
    std::string path("liste_test.txt");
    std::wstring ligne;
    
    std::locale loc("fr_FR.UTF-8");
    std::cout.imbue(loc);
    std::wcout.imbue(loc);
    std::wifstream file(path.c_str(),std::ios::in);
    file.imbue(loc);
    std::cout << "Path = " << path << std::endl;
    std::cout << "1- locale wifstream : " << file.getloc().name() << std::endl;
    std::cout << "2- locale wcout : " << std::wcout.getloc().name() << std::endl;
    std::cout << "3- locale cout : " <<  std::cout.getloc().name() << std::endl;
    /* Pas d'erreur de compile mais ne semble pas avoir d'effet 
    file.imbue(std::locale(file.getloc(),new std::codecvt_utf8<wchar_t,0x10ffff,std::consume_header>));
    std::cout << "1- Variable de localisation : " << file.getloc().name();
    */

    if (file){
        
        //compte les lignes      
        while (std::getline(file,ligne)){
            nbreLigne++;
            dico.push_back(ligne);

            /*
            Erreur de segmentation (core dumped) si cette ligne est activée
            std::wcout << dico[nbreLigne] << std::endl; 
            */
        }
    
        std::cout << "Total lines number = " << nbreLigne << std::endl;
        
    }
    else{
        std::cout << "ERREUR: Impossible d'ouvrir le fichier." << std::endl;
    }

    std::cout << "-------------------" << std::endl;
    std::cout << "Lecture de la variable dico" << std::endl;
    std::cout << std::endl;
    for(int i = 0; i < nbreLigne; i++){
       std::wcout << dico[i] << std::endl;
    }
    
...

如何在cout,wcout和ifstream中正确使用语言环境?

解决方法

为简单回答,没有通用的方法来处理C ++和大多数编程语言中的重音字符。仅ASCII是几乎通用的,并且仅覆盖英文字符。随着时间的流逝,从Windows code pageUTF-8wide-char的低谷诞生了多种处理语言特定字符的解决方案(std::wcout适用于宽字符)。

您的问题不是您的程序(除非在这种情况下,它仅应使用std::cout),而是您的词典使用的字符集与终端的字符集不同。

解决字符集问题既困难又无聊。对于您而言,以UTF-8或使用iconv(1)手工重写字典是值得的。在实际的项目中,您将使用GNU gettext之类的国际化(i18n)工具来为您处理此负担。今天,大多数现代系统都使用UTF-8。

此外,在C ++流上设置语言环境仅会更改<<浮点数时程序格式值(如小数点分隔符)的方式,它无法更改控制台语言环境,因为std::cin不一定是终端而且可能很奇怪。