一、用eclipse打开txt文件出现乱码如下:
工作当中用eclipse打开txt文件出现乱码如下那该怎样解决呢?
选中该txt文件,然后右键选择properties属性,找到text file encoding,选中other,下拉找到gbk,有可能没有GBK选项则直接输入即可。
点击apply,则文件能正常打开了!
二、常见的UTF-8、GBK、UNICODE之间的区别和联系
Unicode是国际通用的一种编码标准,它包含着世界上各个国家的所有符号且每一个符号都对应着一个全球唯一的数字。每一个符号在计算机物理层存储的都是二进制,但是有些字符像英文字母只需要用一个字节就能表示,有的符号可能要用很多字节表示,计算机无法知道哪个符号用几个字节表示,要是全部统一用固定字节就会造成大量的浪费,如何解决这个问题?
西方人提出了一种编码方式就是utf-8(utf16/utf32),是变长编码,英文只用一个字节即可,汉字要用三个字节;
针对汉字编码的问题,专门提出了gbk,每个符号用两个字节表示,比utf8的方式占用资源少。
因此,处理的文本主要为中文时最好用gbk编码,英文较多时用utf8编码。
gbk和utf8两种编码之间转换要通过unicode来间接实现。
一个符号可通过unicode码表查到二进制数表示,再将其转化成utf8(gbk)编码的形式存贮;解码时将utf8(gbk)转化成unicode,就可还原符号。
三、GBK、UTF8、UNICODE编码转换
string GBKToUTF8(const std::string& strGBK)
{
int nLen = MultiByteToWideChar(CP_ACP, 0, (), -1, NULL, 0);
WCHAR * wszUTF8 = new WCHAR[nLen];
MultiByteToWideChar(CP_ACP, 0, (), -1, wszUTF8, nLen);
nLen = WideCharToMultiByte(CP_UTF8, 0, wszUTF8, -1, NULL, 0, NULL, NULL);
char * szUTF8 = new char[nLen];
WideCharToMultiByte(CP_UTF8, 0, wszUTF8, -1, szUTF8, nLen, NULL, NULL);
std::string strTemp(szUTF8);
delete[]wszUTF8;
delete[]szUTF8;
return strTemp;
}
string UTF8ToGBK(const std::string& strUTF8)
{
int nLen = MultiByteToWideChar(CP_UTF8, 0, (), -1, NULL, 0);
unsigned short * wszGBK = new unsigned short[nLen + 1];
memset(wszGBK, 0, nLen * 2 + 2);
MultiByteToWideChar(CP_UTF8, 0, (), -1, (LPWSTR)wszGBK, nLen);
nLen = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)wszGBK, -1, NULL, 0, NULL, NULL);
char *szGBK = new char[nLen + 1];
memset(szGBK, 0, nLen + 1);
WideCharToMultiByte(CP_ACP,0, (LPWSTR)wszGBK, -1, szGBK, nLen, NULL, NULL);
std::string strTemp(szGBK);
delete[]szGBK;
delete[]wszGBK;
return strTemp;
}
std::string Gbk2Unicode(std::string &strValue)
{
std::string strReturn;
unsigned char chTemp;
int nLength = ()*4+1;
WCHAR *pwchBuf = new WCHAR[nLength];
memset(pwchBuf, 0, sizeof(WCHAR) * nLength);
MultiByteToWideChar(CP_ACP, 0, (), -1, (LPWSTR)pwchBuf, nLength);
for (size_t i = 0; i < wcslen(pwchBuf); i++)
{
strReturn += "\\u";
chTemp = *((unsigned char*)pwchBuf+i*2+1);
if(chTemp)
{
strReturn += m_cl( (unsigned char)(chTemp >> 4) );
strReturn += m_cl( (unsigned char)(chTemp % 16) );
}
chTemp = *((unsigned char*)pwchBuf+i*2);
strReturn += m_cl( (unsigned char)(chTemp >> 4) );
strReturn += m_cl( (unsigned char)(chTemp % 16) );
}
delete[]pwchBuf;
pwchBuf = NULL;
return strReturn;
}
std::string Gbk2Unicode(std::string &strValue)
{
std::string strReturn;
unsigned char chTemp;
int nLength = ()*4+1;
WCHAR *pwchBuf = new WCHAR[nLength];
memset(pwchBuf, 0, sizeof(WCHAR) * nLength);
MultiByteToWideChar(CP_ACP, 0, (), -1, (LPWSTR)pwchBuf, nLength);
for (size_t i = 0; i < wcslen(pwchBuf); i++)
{
strReturn += "\\u";
chTemp = *((unsigned char*)pwchBuf+i*2+1);
if(chTemp)
{
strReturn += m_cl( (unsigned char)(chTemp >> 4) );
strReturn += m_cl( (unsigned char)(chTemp % 16) );
}
chTemp = *((unsigned char*)pwchBuf+i*2);
strReturn += m_cl( (unsigned char)(chTemp >> 4) );
strReturn += m_cl( (unsigned char)(chTemp % 16) );
}
delete[]pwchBuf;
pwchBuf = NULL;
return strReturn;
}
std::string Unicode2GBK(std::string &strValue)
{
std::vector<std::string> vcString;
MyTools::SplitString(strValue, "\\u", vcString);
wchar_t* pwBuf = new wchar_t[() + 1];
memset(pwBuf, 0, (() + 1)* sizeof(wchar_t));
int j(0);
for(std::vector<std::string>::iterator it = vcS(); it != vcS(); ++it)
{
if (it->empty())
{
continue;
}
unsigned short wcTmp = 0;
unsigned char cTmp = 0;
//因为有中文字符混合ASSCII码情况,所以条件为k < it->length()
for(size_t k = 0; k < it->length(); ++k)
{
cTmp = (unsigned char)(*it)[k];
if(cTmp <= '9')//0x30~0x39 即0~9
{
wcTmp |= (cTmp & 0x0f) << (it->length() - k - 1) * 4;
}
else if(cTmp >= 'a')//0x61~7a 即a~z
{
wcTmp |= (cTmp - 0x57) << (it->length() - k - 1) * 4;
}
else//0x41~5a 即A~Z
{
wcTmp |= (cTmp - 0x37) << (it->length() - k - 1) * 4;
}
}
pwBuf[j++] = (wchar_t)wcTmp;
}
char *pDst = new char[() + 1];
memset(pDst, 0, (() + 1) * sizeof(char));
WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, (char*)pDst, () - 1, NULL, NULL);
std::string strRet(pDst);
delete[]pwBuf;
pwBuf= NULL;
delete[]pDst;
pDst=NULL;
return strRet;
}
四、那该怎样深入地理解编码方式呢?
步骤 1 :
编码概念
顶折
计算机存放数据只能存放数字,所有的字符都会被转换为不同的数字。
就像一个棋盘一样,不同的字,处于不同的位置,而不同的位置,有不同的数字编号。
有的棋盘很小,只能放数字和英文
有的大一点,还能放中文
有的“足够”大,能够放下世界人民所使用的所有文字和符号
如图所示,英文字符 A 能够放在所有的棋盘里,而且位置都差不多
中文字符, 中文字符 中 能够放在后两种棋盘里,并且位置不一样,而且在小的那个棋盘里,就放不下中文
步骤 2 :
常见编码
顶折
工作后经常接触的编码方式有如下几种:
ISO-8859-1 ASCII 数字和西欧字母
GBK GB2312 BIG5 中文
UNICODE (统一码,万国码)
其中
ISO-8859-1 包含 ASCII
GB2312 是简体中文,BIG5是繁体中文,GBK同时包含简体和繁体以及日文。
UNICODE 包括了所有的文字,无论中文,英文,藏文,法文,世界所有的文字都包含其中
步骤 3 :
UNICODE和UTF
顶折
根据前面的学习,我们了解到不同的编码方式对应不同的棋盘,而UNICODE因为要存放所有的数据,那么它的棋盘是最大的。
不仅如此,棋盘里每个数字都是很长的(4个字节),因为不仅要表示字母,还要表示汉字等。
如果完全按照UNICODE的方式来存储数据,就会有很大的浪费。
比如在ISO-8859-1中,a 字符对应的数字是0x61
而UNICODE中对应的数字是 0x00000061,倘若一篇文章大部分都是英文字母,那么按照UNICODE的方式进行数据保存就会消耗很多空间
在这种情况下,就出现了UNICODE的各种减肥子编码, 比如UTF-8对数字和字母就使用一个字节,而对汉字就使用3个字节,从而达到了减肥还能保证健康的效果
UTF-8,UTF-16和UTF-32 针对不同类型的数据有不同的减肥效果,一般说来UTF-8是比较常用的方式
UTF-8,UTF-16和UTF-32 彼此的区别在此不作赘述,有兴趣的可以参考 unicode-百度百科
步骤 4 :
Java采用的是Unicode
顶折
写在.java源代码中的汉字,在执行之后,都会变成JVM中的字符。
而这些中文字符采用的编码方式,都是使用UNICODE. "中"字对应的UNICODE是4E2D,所以在内存中,实际保存的数据就是十六进制的0x4E2D, 也就是十进制的20013。
代码比较复制代码1234567package stream; public class TestStream { public static void main(String[] args) { String str = "中"; }}
步骤 5 :
一个汉字使用不同编码方式的表现
顶折
以字符 中 为例,查看其在不同编码方式下的值是多少
也即在不同的棋盘上的位置
代码比较复制代码代码行数较多,请点击查看
步骤 6 :
文件的编码方式-记事本
顶折
接下来讲,字符在文件中的保存
字符保存在文件中肯定也是以数字形式保存的,即对应在不同的棋盘上的不同的数字
用记事本打开任意文本文件,并且另存为,就能够在编码这里看到一个下拉。
ANSI 这个不是ASCII的意思,而是采用本地编码的意思。如果你是中文的操作系统,就会使GBK,如果是英文的就会是ISO-8859-1
Unicode UNICODE原生的编码方式
Unicode big endian 另一个 UNICODE编码方式
UTF-8 最常见的UTF-8编码方式,数字和字母用一个字节, 汉字用3个字节。
步骤 7 :
文件的编码方式-eclipse
顶折
eclipse也有类似的编码方式,右键任意文本文件,点击最下面的"property"
就可以看到Text file encoding
也有ISO-8859-1,GBK,UTF-8等等选项。
其他的US-ASCII,UTF-16,UTF-16BE,UTF-16LE不常用。
步骤 8 :
用FileInputStream 字节流正确读取中文
顶折
为了能够正确的读取中文内容
1. 必须了解文本是以哪种编码方式保存字符的
2. 使用字节流读取了文本后,再使用对应的编码方式去识别这些数字,得到正确的字符
如本例,一个文件中的内容是字符中,编码方式是GBK,那么读出来的数据一定是D6D0。
再使用GBK编码方式识别D6D0,就能正确的得到字符中
注: 在GBK的棋盘上找到的中字后,JVM会自动找到中在UNICODE这个棋盘上对应的数字,并且以UNICODE上的数字保存在内存中。
代码比较复制代码代码行数较多,请点击查看
步骤 9 :
用FileReader 字符流正确读取中文
顶折
FileReader得到的是字符,所以一定是已经把字节根据某种编码识别成了字符了
而FileReader使用的编码方式是C()的返回值,如果是中文的操作系统,就是GBK
FileReader是不能手动设置编码方式的,为了使用其他的编码方式,只能使用InputStreamReader来代替,像这样:
<br data-filtered="filtered">new InputStreamReader(new FileInputStream(f),C("UTF-8")); <br data-filtered="filtered">
在本例中,用记事本另存为UTF-8格式,然后用UTF-8就能识别对应的中文了。
解释: 为什么中字前面有一个?
如果是使用记事本另存为UTF-8的格式,那么在第一个字节有一个标示符,叫做BOM用来标志这个文件是用UTF-8来编码的。
代码比较复制代码代码行数较多,请点击查看
步骤 10 :
练习-数字对应的中文
顶折
Or
姿势不对,事倍功半! 点击查看做练习的正确姿势
找出 E5 B1 8C 这3个十六进制对应UTF-8编码的汉字
步骤 11 :
答案-数字对应的中文
顶折
查看答案 在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
步骤 12 :
练习-移除BOM
顶折
Or
姿势不对,事倍功半! 点击查看做练习的正确姿势
如果用记事本根据UTF-8编码保存汉字就会在最前面生成一段标示符,这个标示符用于表示该文件是使用UTF-8编码的。
找出这段标示符对应的十六进制,并且开发一个方法,自动去除这段标示符
步骤 13 :
答案-移除BOM
顶折
查看答案 在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多