昨天有人在讨论关于设置System的property,file.encoding 修改defaultcharset无效
Properties pps=System.getProperties(); pps.setProperty("file.encoding","ISO-8859-1");
public static Charset defaultCharset() { if (defaultCharset == null) { synchronized (Charset.class) { java.security.PrivilegedAction pa = new GetPropertyAction("file.encoding"); String csn = (String)AccessController.doPrivileged(pa); Charset cs = lookup(csn); if (cs != null) defaultCharset = cs; else defaultCharset = forName("UTF-8"); } } return defaultCharset; }
当我们在改变System.getProperties里的file.encoding 的时候,defaultCharset已经被初始化过了,所以不会在调用初始话的代码。
当jvm 启动的时候,load class, 最后调用main函数之前,defaultCharset已经初始化好,而很多函数里都掉用了这个方法象String.getBytes, 还有 InputStreamReader, InputStreamWriter 都是调用了 Charset.defaultCharset()的方法,就不去追查谁先调用了defaultCharset。
对defaultCharset,在jvm里的语言就是初始话在启动的时候,而且不可被更改,你只能修改系统的charset,或者jvm的启动参数里加上 -Dfile.encoding="UTF-8"
题外话
在java里面String是使用char数组来表示,而java的char和c的char是不同的,java的char是双字节的, 而c 里面的char单字节,等同于java byte
也就是说我们在转化byte 到string的时候,是根据charset decode转化成char, 而我们在调用println,write string的时候,还是要把char最后encode成byte 输出到控制台,或者文件中。
而在最后调用c函数write 的时候,如果是java 的byte数组,还要转化成c 里的char数组
(*env)->GetByteArrayRegion(env, bytes, off, len, (jbyte *)buf);