自从接触linux,我对文件编码印象深刻。
但是在用windows出现一些问题,关于文件名的编码。
windows有两套编码方案,utf-16和ansi。
utf-16是内部编码方案,ansi是针对不同区域使用的外部编码,例如gbk。
所以这套方案,对于windows语言选择是中文的你则是utf-16和gbk。
通过windows控制面板区域可以使ansi编码在gbk和utf-8之间变换。
但变换的时候发现文件名并没有中文乱码现象,通过搜索得知文件系统为ntfs的文件名采用utf16编码,和ansi无关,所以无论如何变换都不会中文乱码。
但我之前遇到的情况是怎么来的呢?
我发现我的中文乱码情况都是来自解压缩,但是并不是每次解压缩都会出现中文乱码。
我就猜测和压缩格式有关。
果然再多多次来回切换ansi发现:zip压缩和解压缩ansi不一致时会中文乱码,而7zip和rar则不会。
通过zip压缩解压缩前后文件名机内码对比,发现zip压缩和ansi有关。
压缩采用utf-8,解压采用gbk,原本两个字符变成了三个字符,符合中文编码字节大小规律,且通过机内码可以完美转换。
压缩采用gbk,解压缩采用utf-8,文件名中文部分�符号,可以大胆猜测因为gbk机内码合并后变成很大的数,这个数字在utf-8内未定义,所以变成�。
所以我猜测因为压缩算法原因,zip压缩的时候会将文件名以ansi的编码格式压缩解压缩,其他的则统一以某种格式进行压缩解压。
附加java字符转与机内码相互转换方法
public static String str2Hex(String input,String charset) throws UnsupportedEncodingException {
String output = "";
byte[] bytes= input.getBytes(charset);
for (int i=0;i<bytes.length;i++){
output+=Integer.toHexString(Byte.toUnsignedInt(bytes[i]))+" ";//两个十六进制数代表一个字节,每个字节留出空格
}
return output;
}
public static String hex2Str(String input,String charset) throws UnsupportedEncodingException {// 汉字转机内码
byte[] bytes = new byte[input.length() * 2 - 1];
String[] strings = input.split(" ");// 将字符串两个一组分段,保证每一段为1byte
for (int i = 0; i < strings.length; i++) {
int a = Integer.valueOf(strings[i], 16);// 将16进制字符串转换成int类型
bytes[i] = (byte) a;// 将int类型强转为byte类型
}
String output = new String(bytes, charset);
return output;
}