file.encoding详解
来源:互联网 发布:身份证感应器软件 编辑:程序博客网 时间:2024/06/01 22:55
为什么每天都有解决不完的问题,一个问题延伸出来十个问题。虽然大都可以解决,但是也只是停留在解决的层面,终究不是学习之道。
技术不停变更,我相信最本质的原理也就那么几个,一定要挖祖坟
似的学习!
一步一步慢慢来吧~
首先来做几个简单的测试:
测试一
javac -encoding
: -encoding <编码> —- 指定源文件使用的字符编码
对于如下代码:
public class Demo { public static void main(String[] args) { System.out.println(System.getProperty("file.encoding")); System.out.println("hello,中国"); }}
格式以UTF-8无BOM类型保存
我们分别使用cmd(默认GBK编码)和MinTTY(UTF-8编码)来读取该文件
-encoding encoding Set the source file encoding name, such as EUC-JP and UTF-8. If -encoding is not specified, the platform default converter is used.
也就是说,如果不指定encoding,则使用平台默认的转换器。
在简体中文的Windows上,平台默认编码会是GBK,那么javac就会默认假定输入的Java源码文件是以GBK编码的。
我们先来证明这句话:
javac Demo.java
对应的字节码文件:
javac -encoding GBK Demo.java
对应的字节码文件:
如果实际输入的确实是GBK编码(GBK兼容ASCII编码)的文件,那么一切都会正常。
但如果实际输入的是别的编码的文件,例如超过了ASCII范围的UTF-8,那javac读进来的内容就会出问题,就“乱码”了。
我们模拟下以上16进制的获得:
String str = new String("中国".getBytes("UTF-8"), "GBK");System.out.println(str);//涓浗System.out.println(DatatypeConverter.printHexBinary(str.getBytes("UTF-8")));//E6B693EE859EE6B597
以下我故意引入一个UTF-8编码的逗号,编译就报错了。
测试二
java -Dfile.encoding 是用来干什么的?
javac -encoding GBK Demo.java
生成class文件,拖到Ubuntu操作系统中。
Cygwin下的测试结果:
cmd下的测试结果:
针对以上这个图做一些解释:
①、A.java就是一个文本文件(以某种编码格式来存储:UTF-8、GBK、ISO-8859-1等),java编译器要解析这个文本文件并编译生成.class文件。而要想解析它,就必须知道它的编码方式。(javac - encoding charset)
②:以不同编码方式编码的A.java经过Java编译器编译生成了同一个相同的A.class。(字符串以UTF-8格式存储)
字节码解读见:http://blog.csdn.net/x_iya/article/details/77073112
③:java虚拟机以二进制字节流的形式加载A.class,读取该字符串并构建String。
④:输出结果。
可以知道只有①和④才会导致乱码的产生。
从上图可以理解不管采用哪种格式编码的源文件(.java),只要正确告诉编译器,编译器就会得到正确的结果(.class)。同时只要告诉JVM正确的输出流需要的编码格式,JVM总会返回正确编码格式的输出流。
那么要想不产生乱码要注意两个环节:
1. 告诉编译器你的源文件编码格式。
2. 告诉JVM你显示或者构造字符串输出流时希望的编码。
一般的,两者保持一致就可以了。
对于以UTF-8编码的源文件A.java,只要:
javac -encoding UTF-8 A.javajava -Dfile.encoding=UTF-8 A
便可以解决乱码问题。
也许你会说命令行下依旧是乱码,那是命令行的问题(chcp 936),调整为chcp 65001, 或者在Cygwin命令行下使用。
另外String.getBytes()
等价于 String.getBytes(Charset.defaultCharset())
,在实际编程中推荐使用带参数的。Charset.defaultCharset()
在Windows中文操作系统中是GBK。
当然也不是一成不变的,可以使用java -Dfile.encoding
指定。
@Test public void testAvailableCharsets() { //Java虚拟机编码方式 System.out.println("defaultCharset:" + Charset.defaultCharset().name()); //所有Java支持的字符集 Charset.availableCharsets().forEach((s, charset) -> System.out.println(s + ":" + charset)); }
模拟下Java读取、编译、运行*.java
的过程:
import javax.xml.bind.DatatypeConverter;import java.io.UnsupportedEncodingException;public class Test { /** * 模拟 javac -encoding * 实现 *.java --> *.class * * @param str 字符串 * @param charset 实际字符串编码格式 * @param encoding 假设的文件编码格式 * @return *.class 字节里的字节序列 */ private static byte[] compile(String str, String charset, String encoding) { try { //读取(对应于图中的①) str = new String(str.getBytes(charset), encoding); //编码到*.class中(对应于图中的②) return str.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } //模拟结果输出 private static String run(byte[] buf, String charset, String encoding) { try { //对应于图中的③ String str = new String(buf, "UTF-8"); //对应于图中的④ return new String(str.getBytes(encoding), charset); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } public static void main(String[] args) throws UnsupportedEncodingException { String str = "中国"; String charset = "UTF-8"; String encoding = "GBK"; //等价于 javac -encoding %encoding% *.java(以 charset 格式编码的源文件) // compileBytes 数组即为 str 在 *.class 的表示 byte[] compileBytes = compile(str, charset, encoding); System.out.println(DatatypeConverter.printHexBinary(compileBytes)); System.out.println(run(compileBytes, charset, encoding)); }}
参考:
https://www.zhihu.com/question/30977092
http://abingsky37.github.io/java_encode.html
http://www.wuxinjian.com/2017/01/08/Java中的字符编码与乱码/
http://blog.csdn.net/u010234516/article/details/52842170
我们遇到的很多核心或者本质问题,也就那一小撮人能够解决。而我们要做的就是要成为那一小撮人。
在此感谢下RednaxelaFX大神。
- file.encoding详解
- Encoding-Decoding: file-encoding
- System.getProperty("file.encoding")
- file error / encoding
- 关于file.encoding的设置
- myecplise text-file-encoding设置
- 关于file.encoding的设置
- System property 之 file.encoding
- Tomcat 设置 Java File encoding
- Jboss 5/6 Reading/File Encoding Problem
- tomcat启动时候file.encoding的问题
- java中的file.encoding属性到底是什么?
- file was loaded in the wrong encoding
- tomcat启动时候file.encoding的问题
- Encoding
- Encoding
- encoding
- Encoding
- umount.nfs: /home/ftphome: device is busy
- 高并发处理中缓存、降级、限流技术
- 专业名词
- Android Studio Library projects cannot set applicationId
- 关于git 关于
- file.encoding详解
- tomcat服务器设置文件下载
- 10个最佳Es6 特性
- 探秘Java中的String、StringBuilder以及StringBuffer
- 《Java NIO文档》非阻塞式服务器
- 用vue构建项目笔记5(在vue-cli项目中引用公用方法)(vue resource统一处理)
- git常用命令
- 2---C语言|笔记【对C语言指针的初步理解】
- 进程与线程-通俗易懂的解释