c++ - C++ 正确使用 cout wcout ifstream 读取带有重音字符的文本文件
问题描述
我想在 Ubuntu 20.04 上读取一个 txt 编码的 UTF8 文件。
我在 wcout cout 和 ifstream 中添加了一个语言环境 fr_FR.UTF-8。
我在想只添加语言环境就足够了。
输出给出了这个:
这是我的代码
...
#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 代码页到UTF-8槽宽字符(std::wcout
适用于那些宽字符)。
您的问题不是您的程序(除非它应该只std::cout
在这种情况下使用),而是您的字典使用与终端字符集不同的字符集。
解决字符集问题既困难又无聊。在您的情况下,用 UTF-8 手动重写字典或使用iconv(1)
是值得的。在实际项目中,您将使用像GNU gettext这样的国际化(i18n) 工具来为您处理这个负担。今天,大多数现代系统都使用 UTF-8。
此外,在 C++ 流上设置区域设置只会更改程序格式值(如<<
浮点数时的小数分隔符)的方式,它不能更改控制台区域设置,因为std::cin
不一定是终端并且可能非常奇怪。
推荐阅读
- wxpython - 在 wx.Panel 中滚动
- c# - 使用 Linq 从嵌套类中返回一个新对象
- tensorflow - 带 TPU 训练的 Tensorflow 对象检测 API - 显示更精细的 Tensorboard 图
- nginx - 在生产中部署 Vue js 似乎更难
- cron - 脚本后 cron 重启
- keycloak - Keycloak:禁用外部 IDP 的用户名/密码登录
- azure - Azure WebJob - 消息处理延迟
- ios - 优步通用链接(或深度链接、网址方案或任何其他方法)在大多数手机上都不起作用
- php - Artisan 迁移命令没有输出
- css - Angular Flex Layout refuses to center container horizontally, applied directives to div, router outlet, everything, yet it still wont center