Java에서 기본 문자 집합/인코딩을 찾는 방법
은 '먹다'를 사용하는 입니다.Charset.defaultCharset()
이게 정답이 아닐 수도 있다는 걸 최근에 알았어요.java.io의 여러 되는 실제 .Java는 기본 문자 집합을 2개 보유하고 있는 것 같습니다.이문 대대 ?해 ?? ?? ???
우리는 하나의 실패 사례를 재현할 수 있었다.이것은 일종의 사용자 오류이지만 다른 모든 문제의 근본 원인을 드러낼 수 있습니다.여기 암호가 있습니다.
public class CharSetTest {
public static void main(String[] args) {
System.out.println("Default Charset=" + Charset.defaultCharset());
System.setProperty("file.encoding", "Latin-1");
System.out.println("file.encoding=" + System.getProperty("file.encoding"));
System.out.println("Default Charset=" + Charset.defaultCharset());
System.out.println("Default Charset in Use=" + getDefaultCharSet());
}
private static String getDefaultCharSet() {
OutputStreamWriter writer = new OutputStreamWriter(new ByteArrayOutputStream());
String enc = writer.getEncoding();
return enc;
}
}
레거시 프로토콜의 일부 혼합 인코딩(ANSI/Latin-1/UTF-8)을 처리하려면 Latin-1의 기본 문자 집합이 필요합니다.따라서 모든 서버는 이 JVM 파라미터를 사용하여 실행됩니다.
-Dfile.encoding=ISO-8859-1
Java 5에 대한 결과는 다음과 같습니다.
Default Charset=ISO-8859-1
file.encoding=Latin-1
Default Charset=UTF-8
Default Charset in Use=ISO8859_1
코드 내에서 file.encoding을 설정하여 인코딩 실행 시간을 변경하려고 합니다.우리 모두는 그것이 효과가 없다는 것을 안다.단, defaultCharset()은 꺼지지만 OutputStreamWriter에서 사용되는 실제 기본 문자 집합에는 영향을 주지 않습니다.
이것은 버그 또는 기능입니까?
EDIT: 승인된 답변은 문제의 근본 원인을 보여줍니다.기본적으로 Java 5에서는 defaultCharset()을 신뢰할 수 없습니다.이것은 I/O 클래스에서 사용되는 기본 인코딩이 아닙니다.Java 6이 이 문제를 수정한 것 같습니다.
거...설정되면 기본 문자 집합이 캐시되고 클래스가 메모리에 있는 동안 변경되지 않습니다.의 설정"file.encoding"
을 지정합니다.System.setProperty("file.encoding", "Latin-1");
아무것도 하지 않습니다. ★★★Charset.defaultCharset()
캐시된 문자 집합을 반환합니다.
결과는 다음과 같습니다.
Default Charset=ISO-8859-1
file.encoding=Latin-1
Default Charset=ISO-8859-1
Default Charset in Use=ISO8859_1
JVM 1.6을 사용하고 있습니다.
(갱신)
JVM 1.5로 버그를 재현했습니다.
소스 코드 1.5를 보면 캐시된 기본 문자 집합이 설정되어 있지 않습니다.이것이 버그인지 아닌지는 모르겠지만 1.6은 이 구현을 변경하고 캐시된 문자 집합을 사용합니다.
JVM 1.5:
public static Charset defaultCharset() {
synchronized (Charset.class) {
if (defaultCharset == null) {
java.security.PrivilegedAction pa =
new GetPropertyAction("file.encoding");
String csn = (String) AccessController.doPrivileged(pa);
Charset cs = lookup(csn);
if (cs != null)
return cs;
return forName("UTF-8");
}
return defaultCharset;
}
}
JVM 1.6:
public static Charset defaultCharset() {
if (defaultCharset == null) {
synchronized (Charset.class) {
java.security.PrivilegedAction pa =
new GetPropertyAction("file.encoding");
String csn = (String) AccessController.doPrivileged(pa);
Charset cs = lookup(csn);
if (cs != null)
defaultCharset = cs;
else
defaultCharset = forName("UTF-8");
}
}
return defaultCharset;
}
을 " "로 하면"file.encoding=Latin-1
에 할 때Charset.defaultCharset()
기본 설정되어 않기 에 이름에 적합한 Latin-1
이 않기 에 찾을 수 없으며 기본 UTF-8
.
/O 등의 가 왜 OutputStreamWriter
결과를
의 sun.nio.cs.StreamEncoder
클래스에서 는1. 11.6 은 JVM 1.6을 기반으로 .Charset.defaultCharset()
기본 인코딩을 가져오는 메서드(IO 클래스에 제공되지 않은 경우)..5 에서는, JVM 1.5 의 방법이 되고 있습니다.Converters.getDefaultEncodingName();
기본 문자 집합을 가져옵니다.는 JVM 시 집합의 합니다.JVM 초기화 시 기본 문자 은 JVM으로 설정됩니다.
JVM 1.6:
public static StreamEncoder forOutputStreamWriter(OutputStream out,
Object lock,
String charsetName)
throws UnsupportedEncodingException
{
String csn = charsetName;
if (csn == null)
csn = Charset.defaultCharset().name();
try {
if (Charset.isSupported(csn))
return new StreamEncoder(out, lock, Charset.forName(csn));
} catch (IllegalCharsetNameException x) { }
throw new UnsupportedEncodingException (csn);
}
JVM 1.5:
public static StreamEncoder forOutputStreamWriter(OutputStream out,
Object lock,
String charsetName)
throws UnsupportedEncodingException
{
String csn = charsetName;
if (csn == null)
csn = Converters.getDefaultEncodingName();
if (!Converters.isCached(Converters.CHAR_TO_BYTE, csn)) {
try {
if (Charset.isSupported(csn))
return new CharsetSE(out, lock, Charset.forName(csn));
} catch (IllegalCharsetNameException x) { }
}
return new ConverterSE(out, lock, csn);
}
하지만 나는 그 댓글에 동의해.이 재산에 의존해서는 안 된다.구현 세부 사항입니다.
이것은 버그 또는 기능입니까?
정의되지 않은 행동처럼 보입니다.실제로 명령줄 속성을 사용하여 기본 인코딩을 변경할 수 있다는 것은 알고 있지만, 이 경우 어떤 일이 발생하는지 정의되어 있지 않습니다.
버그 ID: 4153515 이 속성을 설정할 때 문제가 발생:
이것은 버그가 아닙니다."file.encoding" 속성은 J2SE 플랫폼 사양에서 필요하지 않습니다. Sun 구현에 대한 내부 세부 사항이며 사용자 코드로 검사하거나 수정할 수 없습니다.또, 읽기 전용으로 되어 있기 때문에, 커맨드 라인의 임의의 값이나 프로그램 실행중에, 이 속성을 임의의 값으로 설정하는 것은 기술적으로 불가능합니다.
VM 및 런타임 시스템에서 사용되는 기본 인코딩을 변경하는 권장 방법은 Java 프로그램을 시작하기 전에 기본 플랫폼의 로케일을 변경하는 것입니다.
나는 사람들이 명령줄에서 인코딩을 설정하는 것을 볼 때 움츠러든다 - 당신은 그것이 어떤 코드에 영향을 미칠지 모른다.
기본 인코딩을 사용하지 않으려면 적절한 메서드/컨스트럭터를 통해 원하는 인코딩을 명시적으로 설정하십시오.
그 행동은 사실 그렇게 이상하지 않다.클래스의 실장을 살펴보면, 그 원인은 다음과 같습니다.
Charset.defaultCharset()
5에서 않습니다.Java 5에서는 캐싱하지 .- 속성 설정 및 .encoding 호출
Charset.defaultCharset()
속성에 두 번째 합니다.「 수 없기 에, 「Latin-1」이라고 하는 이름의 문자 세트를 찾을 수 없습니다.이 경우 "Latin-1"이라는 이름의 문자 세트는 발견되지 않습니다.Charset.defaultCharset()
UTF-8로 하다 OutputStreamWriter
, 하고 있으며 중에 이미 이 높기 에 디폴트 합니다.Charset.defaultCharset()
실행 시 시스템 속성 "file.filename"이 변경되었는지 확인합니다.
이미 지적한 바와 같이 이러한 상황에서 VM이 어떻게 동작해야 하는지에 대해서는 문서화되어 있지 않습니다.그Charset.defaultCharset()
API 문서에서는 기본 문자 집합의 결정 방법에 대해서는 그다지 정확하지 않습니다.일반적으로 OS 기본 문자 집합이나 기본 로케일 등의 요소에 따라 VM 부팅 시 수행된다는 것만 언급하고 있습니다.
우선, Latin-1은 ISO-8859-1과 같기 때문에, 디폴트는 이미 OK였습니다.그렇죠?
명령줄 파라미터를 사용하여 부호화를 ISO-8859-1로 설정했습니다.프로그래밍 방식으로 "Latin-1"로 설정할 수도 있지만, 이는 Java용 파일 인코딩의 인식된 값이 아닙니다.http://java.sun.com/javase/6/docs/technotes/guides/intl/encoding.doc.html 를 참조해 주세요.
이 경우, 송신원으로부터 Charset가 UTF-8로 리셋 되는 것처럼 보입니다.그게 적어도 대부분의 행동을 설명해 주는군요.
Output Stream Writer가 ISO8859_1을 표시하는 이유를 알 수 없습니다.closed-source sun.misc.* 클래스에 위임됩니다.같은 메커니즘으로 인코딩을 처리하는 것은 아닌 것 같습니다만, 이상합니다.
그러나 물론 이 코드에서는 항상 인코딩을 지정해야 합니다.플랫폼 디폴트에는 절대 의존하지 않습니다.
WAS 서버의 vm 인수를 -Dfile.encoding=으로 설정했습니다.UTF-8을 사용하여 서버의 기본 문자 집합을 변경합니다.
확인.
System.getProperty("sun.jnu.encoding")
시스템 명령줄에서 사용되는 인코딩과 동일한 것 같습니다.
언급URL : https://stackoverflow.com/questions/1749064/how-to-find-the-default-charset-encoding-in-java
'source' 카테고리의 다른 글
C#의 null-coalesing 연산자와 동등한 Python이 있습니까? (0) | 2022.11.16 |
---|---|
Swing GUI에 공백 공간 제공 (0) | 2022.11.16 |
POSTMAN 요청을 Curl로 변환 (0) | 2022.11.16 |
키가 있는 어레이의 루프용 트위그 (0) | 2022.11.16 |
Mariadb의 함수 호출로 제약 조건 검사를 추가할 수 없습니다. (0) | 2022.11.16 |