fstream类读取UTF-8、Unicode和ANSI文本文档乱码问题的解决方案

原文链接:https://my.oschina.net/duluo180/blog/17457


1、解决UTF-8类型的文本文档中文乱码读取(思路:将UTF-8转成Unicode然后再转ANSI)

#include <fstream>
#include <iostream>
#include <string>
// #include <afx.h>
#include <Windows.h>
//changeTextFromUtf8ToAnsi读取UTF-8格式的文件并将之保存为ANSI格式的文件
void changeTextFromUtf8ToAnsi(const char* filename)
{
ifstream infile;string strLine="";string strResult="";
infile.open(filename);
if (infile)
{
   while(!infile.eof()){
    getline(infile,strLine);
    strResult+=strLine+"\n";
   }
}
infile.close();
char* changeTemp=new char[strResult.length()];
strcpy(changeTemp,strResult.c_str());
char* changeResult=changeTxtEncoding(changeTemp);
strResult=changeResult;
ofstream outfile;
outfile.open("I:\\ANSI.txt");
outfile.write(strResult.c_str(),strResult.length());
outfile.flush();
outfile.close();
}
//changeTxtEncoding修改字符串的编码
char* changeTxtEncoding(char* szU8){ 
int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), NULL, 0);
wchar_t* wszString = new wchar_t[wcsLen + 1];
::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), wszString, wcsLen);
wszString[wcsLen] = '\0';
cout<<wszString<<endl;

int ansiLen = ::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), NULL, 0, NULL, NULL);
char* szAnsi = new char[ansiLen + 1];
::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), szAnsi, ansiLen, NULL, NULL);
szAnsi[ansiLen] = '\0';
return szAnsi;
}

2、解决Unicode类型的文本文档中文乱码读取(此方法经测试不可用于打开ANSI的文本文档)

string ws2s(const std::wstring& ws)和string readTxt(char* filename)函数转帖自CSDN,readTxt函数由本人进行了一个小小的bug修正,从而可以避免末字符重复出现的问题;
// fstream中文乱码解决方案.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
string ws2s(const std::wstring& ws);
string readTxt(char* filename);
int _tmain(int argc, _TCHAR* argv[])
{
readTxt("E:\\testUnicode.txt");
}

std::string ws2s(const std::wstring& ws)
{
std::string curLocale = setlocale(LC_ALL, NULL); // curLocale = "C";
setlocale(LC_ALL, "chs");
const wchar_t* _Source = ws.c_str();
size_t _Dsize = 2 * ws.size() + 1;
char *_Dest = new char[_Dsize];
memset(_Dest,0,_Dsize);
wcstombs(_Dest,_Source,_Dsize);
std::string result = _Dest;
delete []_Dest;
setlocale(LC_ALL, curLocale.c_str());
return result;
}
std::string readTxt(char* filename) {
ifstream fin;
fin.open(filename, ios::binary);
size_t index = 2;
std::string strRet;
std::string strLineAnsi;
std::wstring wstrLine;
while (!fin.eof())
{
   fin.seekg(index, ios::beg);
   wchar_t wch;
   fin.read((char *)(&wch), 2);
   if (wch == 0x000D) // 判断回车
   {
    strLineAnsi = ws2s(wstrLine);
    wstrLine.erase(0, wstrLine.size() + 1);
    index += 2; // 跳过回车符和行开头符
    strRet = strRet + strLineAnsi;
   }
   else
   {
    wstrLine.append(1, wch);
    index += 2;
   }
}
strLineAnsi = ws2s(wstrLine);
strRet = strRet + strLineAnsi;
fin.close();
//if语句解决文本段末有回车导致最后字符集重复的问题
if (strLineAnsi!="")
{
   strRet=strRet.substr(0,strRet.length()-1);
} 
printf("%s", strRet.c_str());
return strRet;
}

3、解决ANSI类型的文本文档中文乱码读取(此方法经测试不可用于打开Unicode的文本文档)

#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
ifstream infile;
string strResult="";
string strTemp="";
infile.open("E:\\testANSI.txt");
if (infile)
{
   while(!infile.eof())
   {
        getline(infile,strTemp);
     strResult+=strTemp;
   }
}
infile.close();
cout<<strResult;
}

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是您需要的解决方案: 1. 首先,您需要使用 Unicode 编码来读取 UTF-8 文件,因为 UTF-8 使用的是多字节编码。您可以使用 `wifstream` 来打开文件,使用 `wstringstream` 来读取文件内容,并使用 `wstring` 存储读取的字符串。 2. 接下来,您需要将读取到的字符串按照您的需求进行分割。您可以使用 `wistringstream` 将字符串分割成单独的项,并逐个添加到您的 `listctrl` 控件中。 3. 为了避免中文乱码,您需要将您的程序的默认编码设置为 UTF-8。您可以使用以下代码来设置: ``` setlocale(LC_ALL, "en_US.UTF-8"); ``` 4. 最后,根据您的要求,您需要使用 `listctrl` 控件的 `InsertColumn` 和 `InsertItem` 方法来创建至少四行四列的表格,并将分割后的项逐个添加到表格中。 下面是一个完整的示例代码,您可以参考一下: ```c++ #include <fstream> #include <sstream> #include <vector> #include <iostream> #include <locale.h> #include <afxwin.h> using namespace std; int main() { // 设置默认编码为 UTF-8 setlocale(LC_ALL, "en_US.UTF-8"); // 打开文件 wifstream file("test.txt"); // 读取文件内容 wstringstream buffer; buffer << file.rdbuf(); wstring content = buffer.str(); // 分割字符串 vector<wstring> items; wistringstream iss(content); wstring item; while (getline(iss, item, L'\t')) { items.push_back(item); } // 创建表格 CListCtrl listctrl; listctrl.Create(WS_VISIBLE | WS_BORDER | LVS_REPORT, CRect(10, 10, 300, 200), NULL, NULL); listctrl.InsertColumn(0, L"列1", LVCFMT_LEFT, 100); listctrl.InsertColumn(1, L"列2", LVCFMT_LEFT, 100); listctrl.InsertColumn(2, L"列3", LVCFMT_LEFT, 100); listctrl.InsertColumn(3, L"列4", LVCFMT_LEFT, 100); // 添加数据 int row = 0; for (int i = 0; i < 16; i += 4) { listctrl.InsertItem(row, items[i].c_str()); listctrl.SetItemText(row, 1, items[i + 1].c_str()); listctrl.SetItemText(row, 2, items[i + 2].c_str()); listctrl.SetItemText(row, 3, items[i + 3].c_str()); row++; } return 0; } ``` 注意:由于我不知道您的具体环境和要求,以上代码可能需要进行一些修改才能正常运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值