如何在 Java 中的 ISO-8859-1 和 UTF-8 之间进行转换?
Posted
技术标签:
【中文标题】如何在 Java 中的 ISO-8859-1 和 UTF-8 之间进行转换?【英文标题】:How do I convert between ISO-8859-1 and UTF-8 in Java? 【发布时间】:2010-10-13 17:20:29 【问题描述】:有人知道如何将字符串从 ISO-8859-1 转换为 UTF-8 并返回到 Java 中吗?
我从 Web 获取一个字符串并将其保存在 RMS (J2ME) 中,但我想保留特殊字符并从 RMS 获取字符串,但使用 ISO-8859-1 编码。我该怎么做?
【问题讨论】:
Encoding conversion in java的可能重复 【参考方案1】:一般来说,您不能这样做。 UTF-8 能够编码任何 Unicode 代码点。 ISO-8859-1 只能处理其中的一小部分。因此,从 ISO-8859-1 转码到 UTF-8 是没有问题的。当发现不受支持的字符时,从 UTF-8 倒退到 ISO-8859-1 会导致“替换字符”(�) 出现在您的文本中。
转码文本:
byte[] latin1 = ...
byte[] utf8 = new String(latin1, "ISO-8859-1").getBytes("UTF-8");
或
byte[] utf8 = ...
byte[] latin1 = new String(utf8, "UTF-8").getBytes("ISO-8859-1");
您可以使用较低级别的Charset
API 进行更多控制。例如,您可以在发现不可编码的字符时引发异常,或使用不同的字符替换文本。
【讨论】:
有关字符编码的更多信息以及为什么从 UTF-8 到 ISO-8859(或 ASCII 或 ANSI)没有多大意义,请参阅以下说明:@987654322 @ 这是来自上述链接的一个很好的总结:There are hundreds of traditional encodings which can only store some code points correctly and change all the other code points into question marks. Some popular encodings of English text are Windows-1252 (the Windows 9x standard for Western European languages) and ISO-8859-1, aka Latin-1 (also useful for any Western European language). But try to store Russian or Hebrew letters [or special chars] in these encodings and you get a bunch of question marks. UTF 7, 8, 16, and 32 all have the nice property of being able to store any code point correctly.
值得一提的是,Windows-1252 (Windows Latin 1) 通过填充一些“Unicode 控制”字符 0x80 - 0xbf 扩展了 ISO-8859-1(官方拉丁语 1)。甚至 Mac 和 Linux 上的浏览器也尊重这一点。所以在某些地方改用 Windows-1252。【参考方案2】:
这对我有用: (“üzüm bağları”是正确的土耳其语书写)
将 ISO-8859-1 转换为 UTF-8:
String encodedWithISO88591 = "üzüm baÄları";
String decodedToUTF8 = new String(encodedWithISO88591.getBytes("ISO-8859-1"), "UTF-8");
//Result, decodedToUTF8 --> "üzüm bağları"
将 UTF-8 转换为 ISO-8859-1
String encodedWithUTF8 = "üzüm bağları";
String decodedToISO88591 = new String(encodedWithUTF8.getBytes("UTF-8"), "ISO-8859-1");
//Result, decodedToISO88591 --> "üzüm baÄları"
【讨论】:
如果你写下面的代码会发生什么:String a=new String(encodedWithUTF8.getBytes("ISO88591"), "ISO-8859-1")
和String b=new String(encodedWithUTF8.getBytes("ISO88591"), "UTF-8")
?如果字符串采用一种编码,而我们使用另一种编码获取字节,那么幕后发生了什么?
您可以尝试它们并在您的 IDE 上查看结果,如果您关注此 URL docs.oracle.com/javase/7/docs/api/java/lang/…,您将看到方法定义。我不知道这个过程的确切细节。
如果有人需要这个 - 我认为上述命令会执行以下操作:a
将占用 UTF-8
的字节,将它们转换为 ISO
字节,然后使用表格 bytes->chars
ISO
编码来打印字符串。如果是字符串b
,它将使用UTF-8
的表bytes->chars
,因此根据UTF
规则基本上映射ISO
字节。 a
将被打印出来,即使它是 ISO
,因为 Java 不会弄乱它的内部字节存储。 b
可能会损坏,因为ISO
的某些字符将被打印出来,就好像它们属于UTF
编码一样。
是否有任何第三方工具可以将存储库中的所有文件转换为 UTF-8?【参考方案3】:
如果你有String
,你可以这样做:
String s = "test";
try
s.getBytes("UTF-8");
catch(UnsupportedEncodingException uee)
uee.printStackTrace();
如果您有一个“损坏”的String
,那么您做错了,将String
转换为另一种编码的String
显然不是可行的方法!您可以将String
转换为byte[]
,反之亦然(给定编码)。在 Java 中,String
s 是用 UTF-16
编码的 AFAIK,但这是一个实现细节。
假设您有一个InputStream
,您可以读入byte[]
,然后使用将其转换为String
byte[] bs = ...;
String s;
try
s = new String(bs, encoding);
catch(UnsupportedEncodingException uee)
uee.printStackTrace();
甚至更好(感谢埃里克森)像这样使用InputStreamReader
:
InputStreamReader isr;
try
isr = new InputStreamReader(inputStream, encoding);
catch(UnsupportedEncodingException uee)
uee.printStackTrace();
【讨论】:
如果你有一个 InputStream,你应该用 InputStreamReader 包装它。【参考方案4】:这是一个使用字符串输出的简单方法(我创建了一个方法来做到这一点):
public static String (String input)
String output = "";
try
/* From ISO-8859-1 to UTF-8 */
output = new String(input.getBytes("ISO-8859-1"), "UTF-8");
/* From UTF-8 to ISO-8859-1 */
output = new String(input.getBytes("UTF-8"), "ISO-8859-1");
catch (UnsupportedEncodingException e)
e.printStackTrace();
return output;
// Example
input = "Música";
output = "Música";
【讨论】:
【参考方案5】:正则表达式也可以很好并且被有效地使用(将ISO-8859-1
中未涵盖的所有UTF-8字符替换为空格):
String input = "€Tes¶ti©ng [§] al€l o€f i¶t _ - À ÆÑ with some 9umbers as"
+ " w2921**#$%!@# well Ü, or ü, is a chaŒracte⚽";
String output = input.replaceAll("[^\\u0020-\\u007e\\u00a0-\\u00ff]", " ");
System.out.println("Input = " + input);
System.out.println("Output = " + output);
【讨论】:
【参考方案6】:Apache Commons IO Charsets class 可以派上用场:
String utf8String = new String(org.apache.commons.io.Charsets.ISO_8859_1.encode(latinString).array())
【讨论】:
【参考方案7】:这是一个将 UNICODE (ISO_8859_1) 转换为 UTF-8 的函数
public static String String_ISO_8859_1To_UTF_8(String strISO_8859_1)
final StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < strISO_8859_1.length(); i++)
final char ch = strISO_8859_1.charAt(i);
if (ch <= 127)
stringBuilder.append(ch);
else
stringBuilder.append(String.format("%02x", (int)ch));
String s = stringBuilder.toString();
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2)
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
String strUTF_8 =new String(data, StandardCharsets.UTF_8);
return strUTF_8;
测试
String strA_ISO_8859_1_i = new String("الغلاف".getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
System.out.println("ISO_8859_1 strA est = "+ strA_ISO_8859_1_i + "\n String_ISO_8859_1To_UTF_8 = " + String_ISO_8859_1To_UTF_8(strA_ISO_8859_1_i));
结果
ISO_8859_1 strA est = اÙغÙا٠String_ISO_8859_1To_UTF_8 = الغلاف
【讨论】:
【参考方案8】:将 ISO-8859-1 字符串转换为 UTF-8 字符串的最简单方法。
private static String convertIsoToUTF8(String example) throws UnsupportedEncodingException
return new String(example.getBytes("ISO-8859-1"), "utf-8");
如果我们想将 UTF-8 字符串转换为 ISO-8859-1 字符串。
private static String convertUTF8ToISO(String example) throws UnsupportedEncodingException
return new String(example.getBytes("utf-8"), "ISO-8859-1");
此外,一种无需使用 String 类的构造函数即可将 ISO-8859-1 字符串转换为 UTF-8 字符串的方法。
public static String convertISO_to_UTF8_personal(String strISO_8859_1)
String res = "";
int i = 0;
for (i = 0; i < strISO_8859_1.length() - 1; i++)
char ch = strISO_8859_1.charAt(i);
char chNext = strISO_8859_1.charAt(i + 1);
if (ch <= 127)
res += ch;
else if (ch == 194 && chNext >= 128 && chNext <= 191)
res += chNext;
else if(ch == 195 && chNext >= 128 && chNext <= 191)
int resNum = chNext + 64;
res += (char) resNum;
else if(ch == 194)
res += (char) 173;
else if(ch == 195)
res += (char) 224;
char ch = strISO_8859_1.charAt(i);
if (ch <= 127 )
res += ch;
return res;
该方法基于将本网站的 utf-8 编码为 iso-8859-1。 Encoding utf-8 to iso-8859-1
【讨论】:
以上是关于如何在 Java 中的 ISO-8859-1 和 UTF-8 之间进行转换?的主要内容,如果未能解决你的问题,请参考以下文章
在 Jboss 上使用 ISO-8859-1 编码和 JSF 2
java接入易宝支付时,商品名称为UTF-8编码的中文,如何转换成GBK编码的中文