UTF-8 - я не понимаю эту последовательность байтов

У меня есть провайдер данных, который отправляет мне некоторые данные, которые должны быть закодированы с помощью UTF-8. Эти данные представляют эту последовательность байтов:

28 49 4e 54 e2 80 99 4c 29 20  (INT’L) => "(INT’L)"

По какой-то причине, когда моя java-программа получает эти данные и сохраняет их в базе данных, приведенная выше последовательность становится такой:

28 49 4e 54 19 4c 29 20        (INT.L) => "(INT\u0019L)"

Java-программа построена поверх hibernate. Сначала он получает данные от поставщика, сохраняет их в объекте, а затем этот объект сохраняется в базе данных (Postgresql).

Почему я теряю байты (e2 80 99 становится 19)
Как я могу избежать этого?

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

import java.sql.Clob;

//...

public static String convertStreamToString(Clob clob) throws SQLException {
    if (clob == null) {
        return "";
    }

    BufferedReader br = null;
    StringBuilder result = new StringBuilder();

    try {
        br = new BufferedReader(new InputStreamReader(clob.getAsciiStream(), Charset.forName("UTF-8")));
        String lig;
        int n = 0;
        while ((lig = br.readLine()) != null) {
            if (n > 0) {
                result.append("\n");
            }
            result.append(lig);
            n++;
        }
    } catch (IOException ioe) {
         // Exception handling code ...
    } catch (SQLException sqlex) {
         // Exception handling code ...
    } finally {
        IOUtil.close(br);
    }

    return result.toString();
}

// ...

MyEntity entity = ...
oracle.sql.NCLOB clob = ...
entity.setProperty(convertStreamToString(clob));


@Entity
class MyEntity {
     @Column(name="prop", length=100000)
     private String prop;  

     public void setProperty(String value) {
          this.prop=value;
     }
}

2 ответа

Решение

Вы используете getAsciiStream() читать содержимое CLOB. Как следует из названия, этот метод применим только для ASCII; разбивает все не-ASCII символы.

Использовать getCharacterStream метод вместо.

BufferedReader br = null;
StringBuilder result = new StringBuilder();

try {
    br = new BufferedReader(clob.getCharacterStream());
    ....

Я думаю, что тип столбца БД должен поддерживать UTF-8. В Oracle это NVARCHAR, в Postgresql это примерно так

create table test (
    utf8fld varchar(50)
);
Другие вопросы по тегам