如何解决c++文件读写流无法读取中文的问题(vc6.0)
作者:互联网
代码
#include <iostream>
#include <fstream>
#include <locale>
using namespace std;
int main()
{
setlocale(LC_ALL, "chs"); // 设置字符编码环境
char buf;
int x;
wchar_t y, temp;
ifstream is("D:\\存档\\OneDrive\\桌面\\作业\\测试文档.docx", ios::in);
while(is.eof() == false)
{
is.read(&buf,sizeof(buf));
if(int(buf) < 0)
{
y = 0x0000;
y = buf; // 取第一个字节的后4位
y <<= 6; // 为下一个字节的六位准备空间
is.read(&buf,sizeof(buf));
// 取第二个字节的后六位
temp = buf;
temp = temp & (63); // 取出temp的后六位
y |= temp;
y <<= 6; // 为下一个字节的六位准备空间
is.read(&buf, sizeof(buf));
temp = buf;
temp = temp & (63);
y |= temp;
printf("%S", &y);
continue;
}
else
{
y = buf;
printf("%s", &y);
}
}
cout << endl;
is.close();
return 0;
}
运行结果
原理解释
在解决这个问题之前,我们需要先熟悉一下utf-8编码,大多数人认为中文在utf-8编码
里只占两个字节,其实这么表述是有问题的,真正的utf-8编码中,中文占据三个字节,
只不过只有两个字节是用来表示是哪个汉字的而已,具体详见下面这位大佬的文章
从上面的文章和这张图可以知道,ascii 表里面有的字符用的是第一种一个字节的编码方式,
而汉字用的是第三种编码方式,所以如果文档中只包含字符和汉字这两种字符的话,只需要
分类处理这两种情况就行了,而从图中可以发现中文编码和其他字符的不同之处:
其他编码(只包含ascii里的字符)的字节都是以0开头的
中文编码的三个字节都是从1开始的
所以,先将一个字节的内容读出来,之后将这个字节强转成为有符号数 int 类型,那么就会
出现所有的中文字符都是负数,所有的非中文字符都是正数,所以,对于强转之后是正数的
情况,直接输出就可以了,对于强转之后是负数的情况,就读取三个字节,之后将1号字节的
后四位取出来,2号字节的后六位取出来,3号字节的后六位取出来,并且将这些取出来的
二进制位重新拼接成为一个16位的字符,之后输出的就是汉字了,如果想要将汉字重新写回
文档并且不发生乱码的话,只需要将是汉字的部分重新构造成上面图中的三个字节编码的格式
写回文档就可以了
另外
这份代码里面的第一行代码是用来设置字符编码环境的
wchar_t 是宽字符,占据16位二进制位,定义原型是 typedef short wchar_t;
sprintf(%S, ..) 中的大S是专门用来输出宽字符的输出格式,这个格式必须在设置完编码格式之后才有效
c++的移位运算是算数移位
10进制的63是 0011 1111,只是c++里面不允许直接使用二进制值,所以我将这串二进制转换成为了十进制
标签:编码,中文,字节,vc6.0,字符,读写,c++,汉字,buf 来源: https://blog.csdn.net/qq_45760401/article/details/118466400