Nơi nhận được chuỗi UTF-8 bằng chữ trong Java?


490

Tôi đang cố gắng sử dụng một hằng thay vì một chuỗi ký tự trong đoạn mã này:

new InputStreamReader(new FileInputStream(file), "UTF-8")

"UTF-8"xuất hiện trong mã khá thường xuyên và sẽ tốt hơn nhiều khi tham khảo một số static finalbiến thay thế. Bạn có biết nơi tôi có thể tìm thấy một biến như vậy trong JDK không?

BTW, trên một ý nghĩ thứ hai, các hằng số như vậy là thiết kế tồi: Văn học tĩnh công cộng ... Không phải là một giải pháp cho sao chép dữ liệu



1
Lưu ý: nếu bạn đã sử dụng Java 7, hãy sử dụng Files.newBufferedWriter(Path path, Charset cs)từ NIO.
Franklin Yu

Câu trả lời:


836

Trong Java 1.7+, java.nio.charset.St ChuẩnCharsets định nghĩa các hằng số để Charsetbao gồm UTF_8.

import java.nio.charset.StandardCharsets;

...

StandardCharsets.UTF_8.name();

Dành cho Android: minSdk 19


3
Bạn có sử dụng .toString () trên đó không?
Matt Broekhuis

54
.toString()sẽ làm việc nhưng chức năng thích hợp là .name(). 99,9% toString không phải là câu trả lời.
Roger

1
btw .displayName()cũng sẽ hoạt động trừ khi nó bị ghi đè để bản địa hóa như dự định.
Roger

36
Bạn thực sự không cần phải gọi name(). Bạn có thể trực tiếp truyền Charsetđối tượng vào hàm InputStreamReadertạo.
Natix

6
Và có những lib khác ngoài đó đòi hỏi một String, có lẽ vì lý do di sản. Trong những trường hợp như vậy, tôi giữ một Charsetđối tượng xung quanh, thường xuất phát từ StandardCharsetsvà sử dụng name()nếu cần.
Magnilex

134

Bây giờ tôi sử dụng org.apache.commons.lang3.CharEncoding.UTF_8hằng từ commons-lang .


4
Đối với những người sử dụng Lang 3.0 : org.apache.commons.lang3.CharEncoding.UTF_8. (Lưu ý "lang3").
Russell Silva

24
Nếu bạn đang sử dụng Java 1.7, hãy xem câu trả lời của @ Rogers bên dưới vì đây là một phần của thư viện chuẩn.
Drew Stephens

2
PS "Câu trả lời của Rogers bên dưới" bây giờ là câu trả lời của @ Roger ở trên . ☝
Gary S.

Lớp đó không được dùng nữa kể từ khi Java 7 giới thiệu java.nio.charset.St
ChuẩnCharsets

66

Các Google Ổi thư viện (mà tôi muốn khuyên bạn nên dù sao, nếu bạn đang làm việc trong Java) có một Charsetslớp học với các lĩnh vực tĩnh như Charsets.UTF_8, Charsets.UTF_16vv

Vì Java 7, bạn chỉ nên sử dụng java.nio.charset.StandardCharsetsthay thế cho các hằng so sánh.

Lưu ý rằng các hằng số này không phải là chuỗi, chúng là các Charsettrường hợp thực tế . Tất cả các API tiêu chuẩn có tên bộ ký tự cũng có tình trạng quá tải lấy một Charsetđối tượng mà bạn nên sử dụng thay thế.


3
Vì vậy, nên là Charsets.UTF_8.name ()?
AlikElzin-kilaka

1
@kilaka Vâng sử dụng tên () thay vì getDisplayName () vì tên () là cuối cùng và getDisplayName () không phải
RKumsher

3
@Buffalo: Vui lòng đọc lại câu trả lời của tôi: nó khuyên bạn nên sử dụng java.nio.charset.StandardCharsetskhi có thể, đây không phải là mã của bên thứ ba. Ngoài ra, các định nghĩa của Guava Charsets không "được sửa đổi liên tục" và AFAIK chưa bao giờ phá vỡ tính tương thích ngược, vì vậy tôi không nghĩ rằng sự chỉ trích của bạn được bảo đảm.
Daniel Pryden

2
@Buffalo: Đó là có thể, nhưng tôi nghi ngờ vấn đề của bạn có liên quan đến Charsetslớp học. Nếu bạn muốn phàn nàn về Guava, điều đó tốt, nhưng đây không phải là nơi dành cho những lời phàn nàn đó.
Daniel Pryden

1
Vui lòng không bao gồm thư viện nhiều megabyte để có một chuỗi không đổi.
Jeffrey Blattman

50

Trong trường hợp trang này xuất hiện trong tìm kiếm web của ai đó, kể từ Java 1.7, giờ đây bạn có thể sử dụng java.nio.charset.St ChuẩnCharsets để có quyền truy cập vào các định nghĩa liên tục của bảng mã chuẩn.


Tôi đã cố gắng sử dụng nhưng nó dường như không hoạt động. 'Charset.defaultCharset ());' dường như hoạt động sau khi bao gồm 'java.nio.charset. *' nhưng dường như tôi không thể đề cập rõ ràng đến UTF8 khi tôi đang cố gắng sử dụng 'File.readAllLines'.
Roger

1
@Roger Điều gì có vẻ là vấn đề? Từ những gì tôi có thể thấy, bạn chỉ có thể gọi:Files.readAllLines(Paths.get("path-to-some-file"), StandardCharsets.UTF_8);
cosjav

Tôi không biết vấn đề là gì, nhưng nó đã có tác dụng với tôi sau khi thay đổi thứ gì đó mà tôi không thể nhớ được.
Roger

1
^^ ^ Có lẽ bạn phải thay đổi nền tảng đích trong IDE. Nếu 1.6 là JDK mới nhất của bạn khi bạn cài đặt IDE, thì có lẽ nó đã chọn nó làm mặc định và giữ nó làm mặc định sau khi bạn cập nhật cả IDE và JDK tại chỗ.
Bitbang3r

10

Hằng số này có sẵn (trong số những người khác như: UTF-16, US-ASCII, vv) trong lớp org.apache.commons.codec.CharEncodinglà tốt.


9

Không có cái nào (ít nhất là trong thư viện Java tiêu chuẩn). Các bộ ký tự khác nhau từ nền tảng đến nền tảng vì vậy không có danh sách tiêu chuẩn nào về chúng trong Java.

Có một số thư viện bên thứ 3 chứa các hằng số này. Một trong số đó là Guava (thư viện cốt lõi của Google): http://guava-lologists.googlecode.com/svn/trunk/javadoc/com/google/common/base/Charsets.html


Tôi phải mất một giây để bắt kịp điều này ... Các hằng số Charsets của Guava là (không có gì bất ngờ) Charsets, không phải String. InputStreamReader có một hàm tạo khác lấy Bộ ký tự thay vì chuỗi. Nếu bạn thực sự cần chuỗi, ví dụ: Charsets.UTF_8.name ().
Ed Staub

1
Các bộ ký tự có thể thay đổi từ nền tảng đến nền tảng, nhưng UTF-8 được đảm bảo tồn tại.
tar

3
Tất cả các bộ ký tự được định nghĩa trong StandardCharsetsđược đảm bảo tồn tại trong mọi triển khai Java trên mọi nền tảng.
Krzysztof Krasnoyń

8

Bạn có thể sử dụng Charset.defaultCharset()API hoặc file.encodingtài sản.

Nhưng nếu bạn muốn hằng số của riêng bạn, bạn sẽ cần phải tự xác định nó.


11
Bộ ký tự mặc định thường được xác định bởi các cài đặt hệ điều hành và ngôn ngữ, tôi không nghĩ có bất kỳ đảm bảo nào rằng nó vẫn giữ nguyên cho nhiều lệnh java. Vì vậy, điều này không thay thế cho một "utf-8" tách rời liên tục.
Jorn Horstmann

6

Trong Java 1.7+

Không sử dụng chuỗi "UTF-8", thay vào đó hãy sử dụng Charsettham số loại:

import java.nio.charset.StandardCharsets

...

new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);

4

Nếu bạn đang sử dụng OkHttp cho Java / Android, bạn có thể sử dụng hằng số sau:

import com.squareup.okhttp.internal.Util;

Util.UTF_8; // Charset
Util.UTF_8.name(); // String

2
nó đã bị xóa khỏi OkHttp, vì vậy cách tiếp theo là: Charset.forName("UTF-8").name()khi bạn cần hỗ trợ cho Android thấp hơn API 19+ nếu không bạn có thể sử dụng:StandardCharsets.UTF_8.name()
mtrakal

3

Định nghĩa không đổi cho tiêu chuẩn. Các bộ ký tự này được đảm bảo có sẵn trên mọi triển khai của nền tảng Java. kể từ ngày 1.7

 package java.nio.charset;
 Charset utf8 = StandardCharsets.UTF_8;

0

Lớp org.apache.commons.lang3.CharEncoding.UTF_8không được dùng nữa sau khi Java 7 được giới thiệujava.nio.charset.StandardCharsets

  • @see Tên mã hóa ký tự JRE
  • @since 2.1
  • @deprecated Java 7 đã giới thiệu {@link java.nio.charset.St ChuẩnCharsets}, định nghĩa các hằng số này là
  • Các đối tượng {@link Charset}. Sử dụng {@link Charset # name ()} để nhận các giá trị chuỗi được cung cấp trong lớp này.
  • Lớp này sẽ được gỡ bỏ trong một bản phát hành trong tương lai.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.