故事是这样的,那天和同事讨论上传txt文件,如何能防止文件乱码,其间引出了如下问题:
随着这些问题的解决,对java和unicode,utf-8之间的关系有了更深层的认识.
如何防止上传文件乱码(无论任何语言).
为了支持i18n,我们必须要求上传文件的编码是utf-8或unicode,否则无法实现全语言的支持.utf-8的文件开头会有EF BB BF标志。
用byte array&utf-8构造string,java如何判断几个byte一个中文字符.
因utf-8是变长编码,所以有些字符会是一个字节(如:ascii),有些会是3个(如:中文),
但在用byte array构造string时,jvm是如何判断以几个字节为一组来构造呢?
原来utf-8编码本身有标志可以判断,每个字符的第一个byte前几位是标示位10*,110*,1110*,11110*,其中1的个数代表这个字符有几个字节。
utf-8和unicode的区别.
unicode是定长编码,每个字符都是2 byte,所以在存储ascii时会浪费一个byte的空间。而utf-8是变长unicode编码,在unicode编码基础上进行变长,在存储ascii时只占用一个byte.存储中文时占用3 byte.
一个utf-8 string有几个char,几个byte?
结果是:
6
2
按照上面的结果看好像一个char是3 byte,但java中一个char是2 byte,为什么?
其实java中无论什么字符集string都会以unicode编码来存储,所以每个char都是一个
unicode编码占两个byte。
output:
9
utf-8 bytes:
-1c
-48
-53
-1b
-65
-43
-1c
-46
-46
chars:
4e
2d
56
-3
4e
-46
unicode bytes:
-2
-1
4e
2d
56
-3
4e
-46
-2 -1(FE FF)是unicode big endian标志
fe ff:big endian
ff fe: no big endian
- 1.如何防止上传文件乱码(无论任何语言).
- 2.用byte array&utf-8构造string,java如何判断几个byte一个中文字符.
- 3.utf-8和unicode的区别.
- 4.一个utf-8 string有几个char,几个byte?
随着这些问题的解决,对java和unicode,utf-8之间的关系有了更深层的认识.
如何防止上传文件乱码(无论任何语言).
为了支持i18n,我们必须要求上传文件的编码是utf-8或unicode,否则无法实现全语言的支持.utf-8的文件开头会有EF BB BF标志。
用byte array&utf-8构造string,java如何判断几个byte一个中文字符.
因utf-8是变长编码,所以有些字符会是一个字节(如:ascii),有些会是3个(如:中文),
但在用byte array构造string时,jvm是如何判断以几个字节为一组来构造呢?
原来utf-8编码本身有标志可以判断,每个字符的第一个byte前几位是标示位10*,110*,1110*,11110*,其中1的个数代表这个字符有几个字节。
utf-8和unicode的区别.
unicode是定长编码,每个字符都是2 byte,所以在存储ascii时会浪费一个byte的空间。而utf-8是变长unicode编码,在unicode编码基础上进行变长,在存储ascii时只占用一个byte.存储中文时占用3 byte.
一个utf-8 string有几个char,几个byte?
- String s = "中国";
- byte[] b = s.getBytes("utf-8");
- String s_utf8 = new String(b,"utf-8");
- System.out.println(s_utf8.getBytes("utf-8").length);
- System.out.println(s_utf8.toCharArray().length);
结果是:
6
2
按照上面的结果看好像一个char是3 byte,但java中一个char是2 byte,为什么?
其实java中无论什么字符集string都会以unicode编码来存储,所以每个char都是一个
unicode编码占两个byte。
- import java.io.UnsupportedEncodingException;
- public class TestUtf8File {
- /**
- * @param args
- * @throws UnsupportedEncodingException
- */
- public static void main(String[] args) throws UnsupportedEncodingException {
- String s = "中国人";
- byte[] b = s.getBytes("utf-8");
- String s_utf8 = new String(b,"utf-8");
- System.out.println(s_utf8.getBytes("utf-8").length);
- System.out.println("utf-8 bytes:");
- printByteArray(s_utf8.getBytes("utf-8"));
- System.out.println("chars:");
- printCharArray(s_utf8.toCharArray());
- byte[] unicodeb= s.getBytes("unicode");
- String s_unidode = new String(unicodeb,"unicode");
- System.out.println("unicode bytes:");
- printByteArray(s_unidode.getBytes("unicode"));
- }
- private static void printByteArray(byte[] b){
- for(int i = 0;i < b.length; i++){
- System.out.println((Integer.toString(b[i],16)));
- }
- }
- private static void printCharArray(char[] c){
- for(int i = 0;i < c.length; i++){
- System.out.println(Integer.toString((byte)(c[i]>>8),16));
- System.out.println(Integer.toString((byte)(c[i]&0xff),16));
- }
- }
- }
output:
9
utf-8 bytes:
-1c
-48
-53
-1b
-65
-43
-1c
-46
-46
chars:
4e
2d
56
-3
4e
-46
unicode bytes:
-2
-1
4e
2d
56
-3
4e
-46
-2 -1(FE FF)是unicode big endian标志
fe ff:big endian
ff fe: no big endian