[英]Converting UTF-8 to ISO-8859-1 in Java
我正在阅读XML文档(UTF-8)并最终使用ISO-8859-1在网页上显示内容。 正如预期的那样,有一些字符没有正确显示,例如“
, –
和'
(它们显示为?)。
是否可以将这些字符从UTF-8转换为ISO-8859-1?
这是我编写的代码片段,用于尝试此操作:
BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
byte[] latin1 = sb.toString().getBytes("ISO-8859-1");
return new String(latin1);
我不太确定会出现什么问题,但是我认为它是readLine()引起了悲伤(因为字符串是Java / UTF-16编码的?)。 我尝试的另一种变化是用latin1替换
byte[] latin1 = new String(sb.toString().getBytes("UTF-8")).getBytes("ISO-8859-1");
我已经读过以前关于这个主题的帖子,我正在学习。 在此先感谢您的帮助。
我不确定标准库中是否存在执行此操作的规范化例程。 我不认为“智能”引号的转换是由标准的Unicode规范化程序处理的 - 但是不要引用我。
聪明的做法是转储ISO-8859-1并开始使用UTF-8
。 也就是说,可以将任何通常允许的Unicode代码点编码为编码为ISO-8859-1
的HTML页面。 您可以使用转义序列对它们进行编码,如下所示:
public final class HtmlEncoder {
private HtmlEncoder() {}
public static <T extends Appendable> T escapeNonLatin(CharSequence sequence,
T out) throws java.io.IOException {
for (int i = 0; i < sequence.length(); i++) {
char ch = sequence.charAt(i);
if (Character.UnicodeBlock.of(ch) == Character.UnicodeBlock.BASIC_LATIN) {
out.append(ch);
} else {
int codepoint = Character.codePointAt(sequence, i);
// handle supplementary range chars
i += Character.charCount(codepoint) - 1;
// emit entity
out.append("&#x");
out.append(Integer.toHexString(codepoint));
out.append(";");
}
}
return out;
}
}
用法示例:
String foo = "This is Cyrillic Ya: \u044F\n"
+ "This is fraktur G: \uD835\uDD0A\n" + "This is a smart quote: \u201C";
StringBuilder sb = HtmlEncoder.escapeNonLatin(foo, new StringBuilder());
System.out.println(sb.toString());
在上面,字符LEFT DOUBLE QUOTATION MARK( U+201C
“ )被编码为&#x201C;。 同样编码了几个其他任意代码点。
需要注意这种方法。 如果您的文本需要针对HTML进行转义,则需要在上述代码或“&”符号被转义之前完成。
根据您的默认编码,以下行可能会导致问题,
byte[] latin1 = sb.toString().getBytes("ISO-8859-1");
return new String(latin1);
在Java中,String / Char始终为UTF-16BE。 只有在将字符转换为字节时才会涉及不同的编码。 假设您的默认编码是UTF-8, latin1
缓冲区被视为UTF-8,而某些Latin-1序列可能形成无效的UTF-8序列,您将得到?。
使用Java 8, McDowell的答案可以像这样简化(同时保留对代理对的正确处理):
public final class HtmlEncoder {
private HtmlEncoder() {
}
public static <T extends Appendable> T escapeNonLatin(CharSequence sequence,
T out) throws java.io.IOException {
for (PrimitiveIterator.OfInt iterator = sequence.codePoints().iterator(); iterator.hasNext(); ) {
int codePoint = iterator.nextInt();
if (Character.UnicodeBlock.of(codePoint) == Character.UnicodeBlock.BASIC_LATIN) {
out.append((char) codePoint);
} else {
out.append("&#x");
out.append(Integer.toHexString(codePoint));
out.append(";");
}
}
return out;
}
}
当您实例化String对象时,需要指明要使用的编码。
所以替换:
return new String(latin1);
通过
return new String(latin1, "ISO-8859-1");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.