ChatGPT解决这个技术问题 Extra ChatGPT

设置默认 Java 字符编码

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

我读过 -Dfile.encoding=whatever 曾经是旧 JVM 的方式。由于我不会进入的原因,我没有那种奢侈。

我努力了:

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

并且该属性已设置,但似乎不会导致下面的最终 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());
优秀的评论家伙 - 以及我自己已经在想的事情。不幸的是,有一个我无法控制的底层 String.getBytes() 调用。我目前看到的唯一解决方法是以编程方式设置默认编码。还有其他建议吗?
可能是无关紧要的问题,但是当 UTF8 设置为“UTF8”、“UTF-8”或“utf8”时有区别吗?最近我发现 IBM WAS 6.1 EJB 和 WEB 容器对用于定义编码的字符串(以区分大小写的方式)进行不同的处理。
只是一个细节,但是:更喜欢 UTF-8 到 UTF8(只有前者是标准的)。这仍然适用于 2012 年...
设置或读取 file.encoding 属性是 not supported
@erickson 我仍然不清楚查询,当使用基于字符的 I/O 流(class Readerclass Writer 的所有子类)时,“file.encoding”是否相关?因为 class FileInputStream 是基于字节的 I/O 流,那么为什么要关心基于字节的 I/O 流中的字符集呢?

C
Community

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

Edward Grech points out, 这样的特殊情况,环境变量 JAVA_TOOL_OPTIONS 可以用来指定这个属性,但通常是这样完成的:

java -Dfile.encoding=UTF-8 … com.x.Main

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

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


为了完整起见,我想通过一些技巧来补充一点,您可以得到实际使用的默认编码(如缓存),这要归功于 Gary Cronin: byte [] byteArray = {'a'}; InputStream inputStream = new ByteArrayInputStream(byteArray); InputStreamReader reader = new InputStreamReader(inputStream);字符串 defaultEncoding = reader.getEncoding(); lists.xcf.berkeley.edu/lists/advanced-java/1999-October/…
JDK-4163515 提供了有关在 JVM 启动后设置 file.encoding sysprop 的更多信息。
我在挠头,因为该命令无法在 Windows、linux 和 mac 上完美运行......然后我将 " 放在这样的值周围: java -D"file.encoding=UTF-8" -jar
在 Java Spring Boot 的情况下检查我的答案:stackoverflow.com/a/48952844/986160
d
dwardu

JVM™ Tool Interface 文档...

由于命令行不能总是被访问或修改,例如在嵌入式虚拟机或简单地在脚本中启动的虚拟机中,提供了一个 JAVA_TOOL_OPTIONS 变量,以便在这些情况下可以启动代理。

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

拿起 JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8


你知道“Picked up...”语句会打印在 Tomcat 日志中吗?
嗨 Edward Grech 我感谢您的解决方案。在另一个论坛帖子中解决了我的问题。 stackoverflow.com/questions/14814230/…
@Tiny Java 两者都懂。 stackoverflow.com/questions/6031877/…
L
Lukas Eder

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

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

这样,您将欺骗 JVM,它会认为未设置字符集并使其在运行时再次将其设置为 UTF-8!


NoSuchFieldException 对我来说
为了使黑客工作,您需要假设安全管理器已关闭。如果您无法设置 JVM 标志,那么您可能(可能)也拥有启用了安全管理器的系统。
JDK9 不再 批准这种黑客攻击。 WARNING: An illegal reflective access operation has occurred • WARNING: Illegal reflective access by [..] • WARNING: Please consider reporting this to the maintainers of [..] • WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations • WARNING: All illegal access operations will be denied in a future release
@Enerccio:这不是一个好的答案,这是一个肮脏的黑客,一个等待发生的问题。那应该只用作紧急措施。
@Enerccio:Java“应该”是否有办法设置这一点是有争议的——人们也可以争辩说,开发人员“应该”在相关时明确指定编码。无论如何,从长远来看,这种解决方案有可能造成严重的麻烦,因此“仅供紧急使用”的警告。实际上,即使是紧急使用也是有问题的,因为有一种支持的方式来设置 JAVA_TOOL_OPTIONS ,如另一个答案中所述。
J
Jens

我认为比设置平台的默认字符集更好的方法是调用更安全的 String.getBytes("charsetName"),尤其是当您似乎对影响应用程序部署有限制时,更不用说平台了。这样,您的应用程序就不会依赖于超出其控制范围的事物。

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


M
Marc Novakowski

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


当然,除非您正在编写桌面应用程序并处理一些没有任何编码元数据的用户指定文本 - 那么平台默认编码是您对用户可能使用什么的最佳猜测。
@MichaelBorgwardt“那么平台默认编码是您最好的猜测”您似乎在建议想要更改默认值并不是一个好主意。你的意思是,尽可能使用显式编码,在没有其他可能的情况下使用提供的默认值?
@Raedwald:是的,这就是我的意思。平台默认编码是(至少在最终用户机器上)系统设置的区域设置中的用户通常使用的编码。如果您没有更好的(即特定于文档的)信息,那么您应该使用这些信息。
@MichaelBorgwardt 胡说八道。使用库自动检测输入编码,并使用 BOM 保存为 Unicode。这是处理和对抗编码地狱的唯一方法。
我认为你们两个不在同一页面上。 Michael 谈论解码,而 Raedwald 谈论解码后的处理。
E
Emmanuel.B

尝试这个 :

    new OutputStreamWriter( new FileOutputStream("Your_file_fullpath" ),Charset.forName("UTF8"))

r
randers

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

代码的关键是:

String s = "एक गाव में एक किसान";
String out = new String(s.getBytes("UTF-8"), "ISO-8859-1");

D
Dmitrii Sidenko

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

对于遇到此问题的人,以下文章最终帮助我们追踪了区域设置如何破坏 Java/Tomcat 中的 unicode/UTF-8

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

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


M
Michail Michailidis

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

mvn spring-boot:run -Drun.jvmArguments="-Dfile.encoding=UTF-8"

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

希望这对某人有帮助!


C
Community

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

a) 设置环境变量(即使在 Windows 系统偏好设置中)

JAVA_TOOL_OPTIONS -Dfile.encoding=UTF8

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

 -Dfile.encoding=UTF-8 

 <jvmArguments>
 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8001
 -Dfile.encoding=UTF-8
 </jvmArguments>

B
Berend Menninga

我正在使用 Amazon (AWS) Elastic Beanstalk 并成功将其更改为 UTF-8。

在 Elastic Beanstalk 中,转到配置 > 软件,“环境属性”。添加(名称)JAVA_TOOL_OPTIONS 和(值)-Dfile.encoding=UTF8

保存后,环境将以 UTF-8 编码重新启动。


D
Dov Wasserman

目前尚不清楚您在做什么,也无法控制。如果您可以在目标文件上插入不同的 OutputStream 类,则可以使用 OutputStream 的子类型,它将字符串转换为您定义的字符集下的字节,默认为 UTF-8。如果修改后的 UTF-8 足以满足您的需要,您可以使用 DataOutputStream.writeUTF(String)

byte inbytes[] = new byte[1024];
FileInputStream fis = new FileInputStream("response.txt");
fis.read(inbytes);
String in = new String(inbytes, "UTF8");
DataOutputStream out = new DataOutputStream(new FileOutputStream("response-2.txt"));
out.writeUTF(in); // no getBytes() here

如果这种方法不可行,那么如果您在这里明确说明在数据流和执行环境方面您可以控制和不能控制的内容可能会有所帮助(尽管我知道有时说起来容易做起来难)。祝你好运。


DataInputStream 和 DataOutputStream 是不应该与纯文本文件一起使用的特殊用途类。他们采用的修改后的 UTF-8 与真正的 UTF-8 不兼容。此外,如果 OP 可以使用您的解决方案,他也可以使用正确的工具来完成这项工作:OutputStreamWriter。
p
prabushi samarakoon
mvn clean install -Dfile.encoding=UTF-8 -Dmaven.repo.local=/path-to-m2

命令与 exec-maven-plugin 一起解决了配置 jenkins 任务时出现的以下错误。

Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=512m; support was removed in 8.0
Error occurred during initialization of VM
java.nio.charset.IllegalCharsetNameException: "UTF-8"
    at java.nio.charset.Charset.checkName(Charset.java:315)
    at java.nio.charset.Charset.lookup2(Charset.java:484)
    at java.nio.charset.Charset.lookup(Charset.java:464)
    at java.nio.charset.Charset.defaultCharset(Charset.java:609)
    at sun.nio.cs.StreamEncoder.forOutputStreamWriter(StreamEncoder.java:56)
    at java.io.OutputStreamWriter.<init>(OutputStreamWriter.java:111)
    at java.io.PrintStream.<init>(PrintStream.java:104)
    at java.io.PrintStream.<init>(PrintStream.java:151)
    at java.lang.System.newPrintStream(System.java:1148)
    at java.lang.System.initializeSystemClass(System.java:1192)

F
Febix

在我的项目中解决这个问题。希望它可以帮助某人。

我使用 LIBGDX java 框架,并且在我的 android studio 项目中也遇到了这个问题。在 Mac OS 中编码是正确的,但在 Windows 10 中,特殊字符和符号以及俄语字符显示为以下问题:?????和其他不正确的符号。

更改 android studio 项目设置:File->Settings...->Editor-> File Encodings 在所有三个字段(全局编码、项目编码和下面的默认值)中为 UTF-8。在任何 java 文件集中: System.setProperty("file.encoding","UTF-8");而对于测试打印调试日志: System.out.println("我的项目编码是:"+ Charset.defaultCharset());


t
theseventhsense

在启动应用程序时设置 jvm 参数帮助我解决了这个问题。 java -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8

file.encoding=UTF-8 - 这有助于在文件中包含 Unicode 字符。

sun.jnu.encoding=UTF-8 - 这有助于将 Unicode 字符作为文件系统中的文件名。


l
lizi

我们一起设置了两个系统属性,它使系统将所有内容都转换为 utf8

file.encoding=UTF8
client.encoding.override=UTF-8

client.encoding.override 属性似乎是特定于 WebSphere 的。
L
LMC

在@Caspar 对接受的答案发表评论后,根据 Sun 解决此问题的首选方法是:

“在启动 Java 程序之前更改底层平台的语言环境。”

http://bugs.java.com/view_bug.do?bug_id=4163515

对于码头工人,请参阅:

http://jaredmarkell.com/docker-and-locales/


m
midmaestro

最近我碰到了一家本地公司的 Notes 6.5 系统,发现 webmail 在非中文本地化的 Windows 安装上会显示无法识别的字符。在网上挖了几个星期,几分钟前才弄清楚:

在 Java 属性中,将以下字符串添加到运行时参数

-Dfile.encoding=MS950 -Duser.language=zh -Duser.country=TW -Dsun.jnu.encoding=MS950

UTF-8 设置在这种情况下不起作用。


S
Swarathesh Addanki

如果您使用的是 AZURE,请在 webapp-component.yml 中使用以下设置

systemProperties:
   file.encoding: "UTF8"
   client.encoding.override: "UTF-8"

注意:如果您遇到编码问题,您的请求被替换为“?”这是你的解决方案。