Данные Java POST для проблемы с кодировкой mySQL UTF-8 - PullRequest
1 голос
/ 13 декабря 2011

У меня есть данные POST, которые содержат японскую строку AKB48 ネ申テレビ シーズン3, определенную в jQuery как data.

$("#some_div").load("someurl", { data : "AKB48 ネ申テレビ シーズン3"}) 

Данные поста отправляются сервлету Java:

String data = new String(this.request.getParameter("data").getBytes("ISO-8859-1"), "UTF-8");

Моя программа сохраняет ее в MySQL, но после сохранения данных в базе данных она становится:

AKB48 u30CDu7533u30C6u30ECu30D3 u30B7u30FCu30BAu30F33

Что мне делать, если я хочу сохранить его как в UTF-8? Все мои файлы в UTF-8.

MySQL - это utf8, а вот код

String sql = "INSERT INTO Inventory (uid, item_id, item_data, ctime) VALUES ("
                + inventory.getUid() + ",'"
                + inventory.getItemId() + "','"
                + StringEscapeUtils.escapeJava(inventory.getItemData()) + "',CURRENT_TIMESTAMP)";
    Statement stmt = con.createStatement();
    int cnt = stmt.executeUpdate(sql);

Ответы [ 4 ]

3 голосов
/ 13 декабря 2011

Из приведенного выше примера я могу убедиться, что японская строка корректно сохраняется в вашей базе данных MySQL, но при экранировании Unicode .

Я бы проверил эти пункты по порядку:

  1. Ваши таблицы и столбцы настроены на набор символов и сопоставление для utf8? т.е., CHARACTER SET utf8 COLLATE utf8_general_ci
  2. Явно устанавливаете кодировку набора символов перед POST? request.setCharacterEncoding("UTF-8");
  3. Вы устанавливаете кодировку символов для ваших соединений с БД? Т.е. jdbc:mysql://localhost:3306/YOURDB?useUnicode=true&characterEncoding=UTF8

Как уже отмечали другие, вы не должны использовать этот getBytes трюк. Это, безусловно, испортит значения POSTed.

EDIT

Не используйте StringEscapeUtils.escapeJava, так как это превратит вашу строку в экранированный Unicode. Вот что превращает AKB48 ネ申テレビ シーズン3 в AKB48 u30CDu7533u30C6u30ECu30D3 u30B7u30FCu30BAu30F33.

0 голосов
/ 13 декабря 2011

Какой смысл в строке

String data = new String(this.request.getParameter("data").getBytes("ISO-8859-1"), "UTF-8");

Вы преобразуете китайские (или, по крайней мере, не случайные) символы в байты, используя кодировку ISO-8859-1.Конечно, это не может работать, так как китайские символы не поддерживаются кодировкой ISO-8859-1.И затем вы создаете новую строку из байтов, которые должны представлять символы в кодировке ISO-8859-1, используя кодировку UTF-8.Это, опять же, не имеет никакого смысла.UTF-8 и ISO-8859-1 - это не одно и то же, и только небольшой набор символов имеет одинаковую кодировку в обоих форматах.

Просто используйте

String data = this.request.getParameter("data");

, и все должновсе будет в порядке, при условии, что в столбце таблицы MySQL используется кодировка, которая поддерживает эти символы.

РЕДАКТИРОВАТЬ:

теперь, когда вы показали нам код, используемый для вставки данных в базу данных,Я знаю, откуда все это происходит (хотя предыдущие пункты все еще действительны).Вы делаете

StringEscapeUtils.escapeJava(inventory.getItemData())

Какой смысл?escapeJava используется для получения строки и экранирования специальных символов, чтобы сделать ее действительным литералом Java String.Это не имеет ничего общего с SQL.Используйте подготовленный оператор:

String sql = "INSERT INTO Inventory (uid, item_id, item_data, ctime) VALUES (?, ?, ?, CURRENT_TIMESTAMP);
PreparedStatement stmt = con.prepareStatement();
stmt.setInteger(1, inventory.getUid()); // or setLong, depending on the type
stmt.setString(2, inventory.getItemId());
stmt.setString(inventory.getItemData());
int cnt = stmt.executeUpdate();

PreparedStatement позаботится о правильном экранировании специальных символов SQL.Это лучший инструмент против атаки SQL-инъекцией, и его всегда следует использовать, когда у запроса есть параметры, особенно если параметры поступают от конечного пользователя.См http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html.

0 голосов
/ 13 декабря 2011

Java-строки хранятся в UTF-16. Итак, этот код:

String data = new String(this.request.getParameter("data").getBytes("ISO-8859-1"), "UTF-8");

декодирует строку UTF-16 (которая была перекодирована из UTF-8 в протоколе HTTP) в двоичный массив с использованием кодировки ISO-8859-1 и перекодирует двоичный массив с использованием UTF-8 кодировок. Это почти наверняка не то, что вы хотите.

Что происходит, когда вы используете это?

String data = this.request.getParameter("data");
System.out.println(data);

Если вторая строка генерирует неверные данные, то, скорее всего, ваша проблема в jQuery. Определите, что вы действительно получаете Unicode в своем запросе jQuery:

System.out.println(this.request.getHeader("Content-Encoding"));

Если он не генерирует неверные данные, но данные не сохраняются правильно в mySQL, ваша проблема на уровне базы данных. Убедитесь, что ваш тип столбца поддерживает строки Unicode.

0 голосов
/ 13 декабря 2011

Почему вы не просто извлекаете значение параметра, как this.request.getParameter("data")?

Ваши данные отправляются правильно с использованием URL-кодировки, где каждый символ Юникода заменяется его кодом.Затем вы должны получить значение параметра.Когда вы запрашиваете байты, используя ISO-8859-1, вы на самом деле портите свои данные, потому что строка представлена ​​в виде последовательности, если коды в текстовой форме.

...