1.Java字符串相关

1.1 Java字符串编码方式

Java字符串由char值序列组成。char数据类型是一个采用UTF-16编码表示Unicode码点的编码单元。大多数常用的Unicode字符使用一个编码单元可以表示,而辅助字符需要两个编码单元表示。

强烈建议不要在程序中使用char类型,除非确实需要处理UTF-16编码单元。最好将字符串作为抽象数据类型处理。

1.2 JNI接口

C字符串是以null结尾的字节序列。

JNI由两组操作字符串的函数,一组把Java字符串转换成“改良的UTF-8”字节序列,另一组将它们转换成UTF-16数值数组,也就是jchar数组。

Java字符串与"改良的UTF-8"字节序列相互转换:

jstring (JNICALL *NewStringUTF) (JNIEnv *env, const char *utf);

根据以全0字节结尾的“改良的UTF-8”字节序列,返回一个新的Java字符串对象

jsize (JNICALL *GetStringUTFLength) (JNIEnv *env, jstring str);

返回以UTF-8编码所需的字节个数

const char* (JNICALL *GetStringUTFChars) (JNIEnv *env, jstring str, jboolean *isCopy);

返回指向字符串的“改良UTF-8”编码的指针。直到ReleaseStringUTFChars函数调用前,该指针一直有效。

如果虚拟机使用UTF-16或UTF-32字符作为其内部字符串的表示,该函数会分配一个新的内存块来存储等价的“改良UTF-8”编码字符。

void (JNICALL *ReleaseStringUTFChars) (JNIEnv env, jstring str, const char chars);

通知JVM本地代码不再需要通过GetStringUTFChars返回的指针访问Java字符串。

Java字符串与UTF-16数值数组相互转换(如果C代码使用了Unicode,使用该组转换函数):

jstring (JNICALL *NewString) (JNIEnv *env, const jchar *unicode, jsize len);

根据Unicode字符串返回一个新的Java字符串对象

jsize (JNICALL *GetStringLength) (JNIEnv *env, jstring str);

返回字符串中字符的个数

const jchar *(JNICALL *GetStringChars) (JNIEnv *env, jstring str, jboolean *isCopy);

返回指向字符串的Unicode编码的指针,直到ReleaseStringChars函数调用之前,该指针一直有效。

void (JNICALL *ReleaseStringChars) (JNIEnv *env, jstring str, const jchar *chars);

通知JVM本地代码不再需要通过GetStringChars返回的指针访问Java字符串。

1.3 DataOutput接口方法writeUTF使用改良的UTF-8

writeUTF方法使用“改良的UTF-8”写出字符串。

改良的UTF-8:

首先用UTF-16表示

其结果之后使用UTF-8规则进行编码

修订后的编码方式对于编码大于0xFFFF的字符的处理有所不同,这是为了向后兼容在Unicode还没有超过16位时构建的虚拟机。

2.文本IO

Java针对文本字符使用的是Unicode标准,最常见的编码方式是UTF-8

在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件:

浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器: