如何检查一个字符串是否可以编码为某种编码?

6
以下测试在转换为Latin1时失败,因为非法字符被替换为值为63(问号)的字节。问题在于这些字符最好应该引起某些异常...
  @Test
  public void testEncoding() throws UnsupportedEncodingException {
    final String czech = "Řízeček a šampáňo a žízeň";
    // okay
    final byte[] bytesInLatin2 = czech.getBytes("ISO8859-2");
    // different bytes, but okay
    final byte[] bytesInWin1250 = czech.getBytes("Windows-1250");
    // different bytes, but okay
    final byte[] bytesInUtf8 = czech.getBytes("UTF-8");
    // nonsense; Ř,č,... are not in Latin1 code set!!!
    final byte[] bytesInLatin1 = czech.getBytes("ISO8859-1");

    System.out.println(Arrays.toString(bytesInLatin2));
    System.out.println(Arrays.toString(bytesInWin1250));
    System.out.println(Arrays.toString(bytesInUtf8));
    System.out.println(Arrays.toString(bytesInLatin1));
    System.out.flush();

    final String latin2 = new String(bytesInLatin2, "ISO8859-2");
    final String win1250 = new String(bytesInWin1250, "Windows-1250");
    final String utf8 = new String(bytesInUtf8, "UTF-8");
    final String latin1 = new String(bytesInLatin1, "ISO8859-1");

    Assert.assertEquals("latin2", czech, latin2);
    Assert.assertEquals("win1250", czech, win1250);
    Assert.assertEquals("utf8", czech, utf8);
    Assert.assertEquals("latin1", czech, latin1); // this test will fail!
  }

由于Java的行为,许多情况下数据最终会被损坏。是否有可用的库来验证字符串是否可以使用某种编码进行编码?

2个回答

11

我猜你可能需要查找CharsetEncoder.canEncode(CharSequence)这个方法。

Charset latin2 = Charset.forName("ISO8859-2");
boolean validInLatin2 = latin2.newEncoder().canEncode(czech);
...

1
+1,干得好!我甚至不知道这个存在... 顺便问一下:有哪些CharSequence不能使用UTF-8编码? - fge
@fge:只有无效的(例如,只有半个代理对的)。 - Jon Skeet

1
作为Jon Skeet建议的替代方案,您还可以使用 CharsetEncoder类直接进行编码(使用 encode方法),但是首先调用onMalformedInputonUnmappableCharacter方法来指定编码器在遇到错误输入时应执行的操作。
这样大多数情况下您只需要进行简单的编码调用,但如果出现任何问题,您将收到异常。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接