设置默认的Java字符编码?

342 java utf-8 character-encoding

如何以编程方式正确设置JVM(1.5.x)使用​​的默认字符编码?

我已经读过-Dfile.encoding=whatever以前用于旧JVM的方法......由于我不会进入的原因,我没有那么奢侈.

我试过了:

System.setProperty("file.encoding", "UTF-8");
Run Code Online (Sandbox Code Playgroud)

并且属性已设置,但它似乎不会导致下面的最终getBytes调用使用UTF8:

    System.setProperty("file.encoding", "UTF-8");

    byte inbytes[] = new byte[1024];

    FileInputStream fis = new FileInputStream("response.txt");
    fis.read(inbytes);
    FileOutputStream fos = new FileOutputStream("response-2.txt");
    String in = new String(inbytes, "UTF8");
    fos.write(in.getBytes());
Run Code Online (Sandbox Code Playgroud)

eri*_*son 293

不幸的是,file.encoding必须在JVM启动时指定属性; 当您输入主方法时,由String.getBytes()和使用的字符编码InputStreamReaderOutputStreamWriter已永久缓存的默认构造函数.

正如Edward Grech指出的那样,在这种特殊情况下,环境变量JAVA_TOOL_OPTIONS 用于指定此属性,但通常如下所示:

java -Dfile.encoding=UTF-8 … com.x.Main
Run Code Online (Sandbox Code Playgroud)

Charset.defaultCharset()将反映file.encoding属性的更改,但核心Java库中需要确定默认字符编码的大多数代码不使用此机制.

在编码或解码时,可以查询file.encoding属性或Charset.defaultCharset()查找当前的默认编码,并使用适当的方法或构造函数重载来指定它.

  • 为了完整性,我想补充一点,你可以得到实际使用的默认编码(就像缓存一样),这要感谢Gary Cronin:byte [] byteArray = {'a'}; InputStream inputStream = new ByteArrayInputStream(byteArray); InputStreamReader reader = new InputStreamReader(inputStream); String defaultEncoding = reader.getEncoding(); http://lists.xcf.berkeley.edu/lists/advanced-java/1999-October/001995.html (9认同)
  • [JDK-4163515](http://bugs.java.com/view_bug.do?bug_id=4163515)有关于在JVM启动后设置`file.encoding` sysprop的更多信息. (2认同)
  • 我挠头,原因是该命令在Windows,Linux和Mac上无法正常运行...然后我将“值”放在这样的位置:java -D“ file.encoding = UTF-8” -jar (2认同)

Edw*_*ech 165

来自JVM™工具界面文档......

由于无法始终访问或修改命令行,例如在嵌入式VM中或仅在脚本内深入启动的VM中,JAVA_TOOL_OPTIONS因此提供变量以便在这些情况下可以启动代理.

通过将(Windows)环境变量设置JAVA_TOOL_OPTIONS-Dfile.encoding=UTF8,System每次启动JVM时都会自动设置(Java)属性.您将知道该参数已被选中,因为以下消息将被发布到System.err:

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8

  • `UTF8`或`UTF-8`? (8认同)

小智 65

我有一种绝对有效的hacky方式!

System.setProperty("file.encoding","UTF-8");
Field charset = Charset.class.getDeclaredField("defaultCharset");
charset.setAccessible(true);
charset.set(null,null);
Run Code Online (Sandbox Code Playgroud)

这样你就会欺骗JVM,它会认为charset没有设置,并让它在运行时再次设置为UTF-8!

  • 要使黑客工作,您需要假设安全管理器已关闭.如果您没有办法设置JVM标志,您可能(可能)也启用了安全管理器系统. (9认同)
  • NoSuchFieldException对我来说 (2认同)
  • JDK9不再*批准这个hack了.`警告:发生了非法反射访问操作•警告:[..]非法反射访问•警告:请考虑向[..]的维护人员报告此情况•警告:使用--illegal-access = warn启用警告进一步的非法反射访问操作•警告:在将来的版本中将拒绝所有非法访问操作 (2认同)
  • @Enerccio:这不是一个好的答案,这是一个肮脏的黑客,一个等待发生的问题。这应该只用作紧急措施。 (2认同)

Dov*_*man 38

我认为比设置平台的默认字符集更好的方法,特别是因为你似乎对影响应用程序部署有限制,更不用说平台了,就是调用更安全的方法String.getBytes("charsetName").这样你的应用程序就不依赖于它无法控制的东西.

我个人认为String.getBytes()应该弃用,因为它在我见过的许多情况下都会造成严重问题,开发人员没有考虑可能更改的默认字符集.


Mar*_*ski 18

我无法回答你原来的问题,但我想提供一些建议 - 不要依赖于JVM的默认编码.最好在代码中明确指定所需的编码(即"UTF-8").这样,您就知道它甚至可以跨不同的系统和JVM配置工作.

  • 当然,除非您正在编写桌面应用程序并处理一些没有任何编码元数据的用户指定文本,否则平台默认编码是您对用户可能使用的内容的最佳猜测. (7认同)

小智 12

试试这个 :

    new OutputStreamWriter( new FileOutputStream("Your_file_fullpath" ),Charset.forName("UTF8"))
Run Code Online (Sandbox Code Playgroud)


Lav*_*ixu 7

我尝试了很多东西,但这里的示例代码完美无缺。 关联

代码的关键是:

String s = "?? ??? ??? ?? ?????";
String out = new String(s.getBytes("UTF-8"), "ISO-8859-1");
Run Code Online (Sandbox Code Playgroud)


Mic*_*dis 6

如果您正在使用 Spring Boot 并希望file.encoding在 JVM 中传递参数,您必须像这样运行它:

mvn spring-boot:run -Drun.jvmArguments="-Dfile.encoding=UTF-8"
Run Code Online (Sandbox Code Playgroud)

这对我们来说是必需的,因为我们使用的是JTwig模板,并且操作系统有ANSI_X3.4-1968我们通过System.out.println(System.getProperty("file.encoding"));

希望这可以帮助某人!


小智 5

我们遇到了同样的问题.我们有条不紊地尝试了本文(和其他人)的一些建议但无济于事.我们还尝试添加-Dfile.encoding = UTF8,似乎没有任何工作.

对于遇到此问题的人,以下文章最终帮助我们跟踪描述了语言环境设置如何在Java/Tomcat中打破unicode/UTF-8

http://www.jvmhost.com/articles/locale-breaks-unicode-utf-8-java-tomcat

在〜/ .bashrc文件中正确设置语言环境对我们有用.


小智 5

我的团队在使用 Windows 的机器上遇到了同样的问题..然后设法通过两种方式解决它:

a) 设置环境变量(即使在 Windows 系统首选项中)

JAVA_TOOL_OPTIONS
-Dfile.encoding=UTF8

b) 将以下代码片段引入到您的 pom.xml 中:

 -Dfile.encoding=UTF-8 
Run Code Online (Sandbox Code Playgroud)

之内

 <jvmArguments>
 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8001
 -Dfile.encoding=UTF-8
 </jvmArguments>
Run Code Online (Sandbox Code Playgroud)