Как я могу проверить, является ли String кодируемой в некоторой кодировке?

Следующий тест не пройден на преобразованной латинице1, поскольку недопустимые символы заменяются байтами со значением 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 ответа

Решение

Я подозреваю, что вы ищете CharsetEncoder.canEncode(CharSequence),

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

В качестве альтернативы предложению Джона Скита вы также можете использовать класс CharsetEncoder для непосредственного кодирования (с помощью метода encode), но сначала вызовите методы onMalformedInput и onUnmappableCharacter, чтобы указать, что должен делать кодировщик, когда он обнаруживает неверный ввод.

Таким образом, большую часть времени вы просто делаете простой кодированный вызов, но если что-то пойдет не так, вы получите исключение.

Другие вопросы по тегам