Проблема кодирования из базы данных в javamail - PullRequest
4 голосов
/ 13 января 2011

У меня есть небольшое приложение, которое читает из базы данных Oracle 9i и отправляет данные по электронной почте, используя JavaMail.В базе данных есть NLS_CHARACTERSET = "WE8MSWIN1252", вот и все, CP1252.

Если я запускаю приложение без каких-либо параметров, оно работает нормально, и электронные письма отправляются правильно.Однако у меня есть требование, которое заставляет меня запускать приложение с параметром -Dfile-encoding=utf8, что приводит к тому, что текст отправляется с поврежденными символами.

Я пытался изменить кодировку считываемых данныхиз базы данных, с:

String textToSend = new String(textRead.getBytes("CP1252"), "UTF-8");

Но это не помогает.Я перепробовал все возможные комбинации с CP1252, windows-1252, ISO-8859-1 и UTF-8, но все равно не повезло.

Есть идеи?


Обновление , чтобы уточнитьмоя проблема: когда я делаю следующее:

Statement stat = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
stat.executeQuery("SELECT blah FROM blahblah ...");
ResultSet rs = stat.getResultSet();
String textRead = rs.getString("whatever");

я получаю textRead поврежден, потому что база данных CP1252 и приложение работает в UTF-8.Другой подход, который я пробовал, но тоже не удался:

InputStream is = rs.getBinaryStream("whatever");
Writer writer = new StringWriter();
char[] buffer = new char[1024];
Reader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
while ((n = reader.read(buffer)) != -1) {
    writer.write(buffer, 0, n);
}
String textRead = writer.toString();

Ответы [ 5 ]

2 голосов
/ 10 февраля 2011

Ваш драйвер должен выполнить преобразование автоматически, и поскольку cp-1252 является подмножеством UTF-8, вы не должны терять информацию.

Можете ли вы попробовать следующее: получить строку с ResultSet.getString, записать строку в файл.Откройте файл в редакторе, с помощью которого можно указать набор символов UTF-8 (например, jEdit).

Файл должен содержать данные UTF-8.

1 голос
/ 21 января 2015

У меня была такая же проблема:

База данных Orace с использованием кодировки WE8MSWIN1252, некоторые данные / текст столбца VARCHAR2, содержащие в себе знак евро (€).При отправке текста с использованием JavaMail возникли проблемы с знаком евро.

Наконец-то все работает.Две важные вещи, которые вы должны проверить / сделать:

  • обязательно используйте самую последнюю версию драйвера Oracle JDBC для используемой вами версии Java.
  • укажите кодировку (предпочтительно: UTF-8) в JavaMail, например

    MimeMessage.setSubject (текст строки, «UTF-8»)
    MimeMessage.setText (текст строки, «UTF-8»).

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

    ПРИМЕЧАНИЕ. Поскольку RFC 821 ограничивает почтовые сообщения 7-битным US-ASCII, 8-битные символьные или двоичные данные необходимо кодировать в 7-битный формат.Заголовок электронного письма «Content-Transfer-Encoding» указывает используемую кодировку.Для получения дополнительной информации: http://www.w3.org/Protocols/rfc1341/5_Content-Transfer-Encoding.html
1 голос
/ 13 января 2011

Данные вашей базы данных находятся в windows-1252. Так что - при условии, что драйвер JDBC возвращает его дословно - при попытке преобразовать его в Java String, , то есть кодировку, которую необходимо указать:

Statement stat = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stat.executeQuery("SELECT blah FROM blahblah ...");
byte[] rawbytes = rs.getBytes("whatever");
String textRead = new String(rawbytes, "windows-1252");

Является ли частью требования, чтобы данные отправлялись по почте как UTF-8? Если это так, часть UTF-8 должна находиться на стороне вывода, а не на стороне ввода. Когда у вас есть String данные в Java, они хранятся внутри как UTF-16. Поэтому, когда вы сериализуете его в MimeMessage, вам снова нужно выбрать кодировку:

mimebodypart.setText(textRead, "UTF-8");
1 голос
/ 13 января 2011

Вы, кажется, потерялись в пространстве кодировки - я понимаю это ... :-)

Эта строка

String textToSend = new String(textRead.getBytes("CP1252"), "UTF-8");

не имеет особого смысла.У вас уже есть текст, преобразуйте его в кодированный байт "cp1252" [].Затем вы указываете виртуальной машине обрабатывать байты, как если бы они были "UTF-8" (что является ложью ...).

Короче говоря: если у вас есть строка как в textRead вам не нужно конвертировать его вообще.Если что-то идет не так, либо текст уже гнилой (посмотрите на это в отладчике), либо позже в API.Проверить это и вернуться с более подробной информацией?Где текст, который является неправильным, и где вы в точности читаете его или пишете ...

0 голосов
/ 10 февраля 2011

Можете ли вы сделать преобразование в базе данных? Вместо:

SELECT blah FROM blahblah

Попробуйте

SELECT convert(blah, 'WE8MSWIN1252', 'UTF8') FROM blahblah
...