默认使用 UFT-8 编码
在 Java SE 18 之前的 Java中,标准字符集会因操作系统和语言设置的不同而不同。Java 标准字符集决定了在 JDK 类库的许多方法中如何将字符串转换为字节,反之亦然(例如,在写入和读取文本文件时)。这些方法包括:
-
FileReader
,FileWriter
,InputStreamReader
,OutputStreamWriter
的构造函数。 -
Formatter
和Scanner
的构造函数。 -
URLEncoder.encode()
和URLDecoder.decode()
的静态方法。
当一个应用程序在一个环境中被开发和测试,然后在另一个环境中运行( Java 选择了不同的默认字符集),这可能导致不可预测的行为。
此外,由于较新的类库方法在没有指定字符集的情况下总是使用 UTF-8 ,所以变得更加混乱,例如:
Files.writeString()
, Files.readString()
, Files.newBufferedWriter()
和 Files.newBufferedReader()
方案一:在调用所有将字符串转换成字节的方法时指定字符集,反之亦然。
FileWriter fw = new FileWriter("happy-coding.txt", StandardCharsets.UTF_8); // ... FileReader fr = new FileReader("happy-coding.txt", StandardCharsets.UTF_8); // ... Files.readString(Path.of("happy-coding.txt"), StandardCharsets.UTF_8);
这个方案会导致大量的代码重复,容易出错。
方案二:通过系统属性 "file.encoding "设置默认字符集。
这种方案中的属性值在 Java SE 17 之前(包括 Java SE 17 )中没有正式记录(见 system-properties )。
其次,如上所述,指定的字符集并不用于所有的 API 方法。比如:
public class Jep400Example { public static void main(String[] args) throws IOException { try (FileWriter fw = new FileWriter("happy-coding.txt"); BufferedWriter bw = new BufferedWriter(fw)) { bw.write("ハッピーコーディング!"); } String text = Files.readString(Path.of("happy-coding.txt")); System.out.println(text); } }
让我们用标准编码 US-ASCII 来运行一次该程序。
java -Dfile.encoding=US-ASCII Jep400Example.java
运行结果如下
?????????????????????????????????
结果是垃圾,因为 FileWriter 考虑到了默认编码,但 Files.readString()
忽略了它,总是使用 UTF-8
。只有在你统一使用 UTF-8 的情况下才能正常运行。
java -Dfile.encoding=UTF-8 Jep400Example.java
运行结果如下
ハッピーコーディング!?
在 Java SE 18 中,无论操作系统、地域和语言设置如何,默认编码将始终是 UTF-8,见: JEP 400
另外,系统属性 file.encoding
也可以被合法使用。然而,我们应该谨慎地这样做。
最好的方法是将 -Dfile.encoding
设置为 UTF-8 或完全省略它。
代码示例
package git.snippets.jdk18; import java.nio.charset.Charset; public class UFT8Test { public static void main(String[] args) { System.out.println("Default charset : " + Charset.defaultCharset()); System.out.println("file.encoding : " + System.getProperty("file.encoding")); System.out.println("native.encoding : " + System.getProperty("native.encoding")); System.out.println(Charset.defaultCharset()); System.out.println("你好"); } }
输出结果为:
Default charset : UTF-8 file.encoding : UTF-8 native.encoding : GBK UTF-8 你好
JDK 自带 Web Server
<!DOCTYPE html> <html lang="en"> <head> <Meta charset="UTF-8"> <title>Java自带的WebServer</title> </head> <body> Web Server By JDK18 </body> </html>
C:\jdk\jdk-18\bin\jwebserver.exe
启动后,控制台会打印如下信息
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::". Serving C:\workspace\java_new_features\jdk18_features\src\main\resources and subdirectories on 127.0.0.1 port 8000 URL http://127.0.0.1:8000/
访问 http://127.0.0.1:8000/ 可以看到效果
API 文档注释中支持代码片段
如果我们想把多行代码片段集成到 JavaDoc 中,我们必须通过 <pre>...</pre>
来完成,而且必须与 {@code ...}
相结合,这样做非常麻烦
/** * How to write a text file with Java 7: * * <pre>{@code try (BufferedWriter writer = Files.newBufferedWriter(path)) { * writer.write(text); *}}</pre> */
在 Java SE 18 中,引入了 @snippet
标签,可以用于代码片段的注释
/** * How to write a text file with Java 7: * * {@snippet : * try (BufferedWriter writer = Files.newBufferedWriter(path)) { * writer.write(text); * } * } */
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。