Кодировка JSP UTF
Мне трудно понять, как справиться с этой проблемой:
Я разрабатываю веб-инструмент для итальянского университета, и мне нужно отображать слова с ударением (например, è, ù, ...); иногда я получаю эти слова из таблицы PostgreSql (в кодировке UTF8), но в основном мне приходится читать длинные отрывки из файла. Эти файлы кодируются в формате utf-8 xml и прекрасно отображаются в Smultron или любом редакторе utf-8 (они были созданы при разборе старых файлов python с такими объектами, как è
вместо "è").
Я написал класс Java, который извлекает соответствующие сегменты из файла XML, который работает следующим образом:
String s = parseText(filename, position)
если я записываю возвращенную строку в файл, все выглядит хорошо; проблема в том, что если я сделаю
out.write(s)
на странице JSP я получаю странные символы. Кстати, я использую
String s = getWordFromPostgresql(...)
out.write(s)
в том же JSP, и он показывает ОК.
Любой намек?
Спасибо Никола
Спасибо за ваш ответ, однако эта директива уже есть на странице, но она не работает (на самом деле она "работает", но только для строк, которые я получаю из базы данных). Я думаю, что есть что-то о чтении из файлов, но я не могу понять... они работают в "Java", но не в "JSP" (не могу придумать лучшего объяснения...)
Вот базовый пример, извлеченный из фактического кода: метод для чтения из файлов возвращает Map, от Mark (объекта, представляющего позицию в тексте) до String (содержащего текст):
это на странице.jsp (с указанием utf-директивы в постах выше)
// ...
Map<Mark, String> map = TestoMarkParser.parseMarks(...);
out.write(map.get(m));
и вот результат:
"Fu però così in uso il Genere Enharmonico, che quelli quali vi si esercitavano",
если я помещу тот же код в Java-класс и заменим out.write на System.out.println, результат будет следующим:
"Fu però così in uso il Genere Enharmonico, che quelli quali vi si esercitavano",
Я провел некоторый анализ с помощью шестнадцатеричного редактора, вот он:
оригинальная строка: "fu però così "
в XML-файле: C3 B2
в соответствии с out.write() в файле JSP: E2 88 9A E2 89 A4
как записано в файл через:
FileWriter w = new FileWriter(new File("out.txt"));
w.write(s); // s is the parsed string
w.close();
C3 B2
печать значений каждого символа в виде целого
0: 70 = F
1: 117 = u
2: 32 =
3: 112 = p
4: 101 = e
5: 114 = r
6: 8730 = �
7: 8804 = �
8: 32 =
9: 99 = c
10: 111 = o
11: 115 = s
12: 8730 = �
13: 168 = �
14: 10 = `
4 ответа
В директиве jsp page вы должны попытаться установить тип контента на utf-8, что также установит pageEncoding на utf-8.
<%@page contentType="text/html;charset=UTF-8"%>
UTF-8 не является типом контента по умолчанию в jsp, и из этого возникают всевозможные интересные проблемы. Проблема заключается в том, что основной поток по умолчанию интерпретируется как поток ISO-8859-1. Если вы запишите некоторые байты Юникода в этот поток, они будут интерпретированы как ISO-8859-1. Я считаю, что установка кодировки в utf-8 является лучшим решением.
Изменить: Кроме того, строковая переменная в Java всегда должен быть Unicode. Так что вы всегда должны быть в состоянии сказать
System.out.println(myString)
и увидеть правильный набор символов, приходящий в окне консоли вашего веб-сервера (или просто зайти в отладчик и проверить его). Я подозреваю, что вы будете видеть неправильные символы, когда будете делать это, что заставляет меня думать, что у вас есть проблема с кодированием при построении строки.
У меня есть несколько международных jsp [которые имеют "специальные" международные (относительно английского) символы].
Вставка этого [и только этого, то есть: также никакой директивы contentType (которая сделала дублирующую ошибку contentType)] в верхней части их заставила их сохранить и правильно отобразить:
<%@page pageEncoding="UTF-8"%>
Эта ссылка [http://www.inter-locale.com/codeset1.jsp] помогла мне обнаружить это.
У меня тоже была такая же проблема, все "utf-8" и почему я вижу
бессмысленные символы и проблема была в jsp и она должна быть во главе страницы.
<%request.setCharacterEncoding("utf-8");%>
и все будет хорошо.
String s = parseText(filename, position)
Где этот метод определен? Я предполагаю, что это ваш собственный метод, который открывает файл и извлекает определенный фрагмент данных. Где-то в этом процессе он преобразуется из байтов в символы, возможно, используя кодировку по умолчанию для вашей JVM.
Если кодировка по умолчанию вашей работающей JVM не соответствует фактической кодировке в файле, вы получите неправильные символы в вашей строке. Кроме того, если вы читаете контент, который закодирован в многобайтовой форме (такой как UTF-8), ваша "позиция" может указывать на середину многобайтовой кодировки.
Если исходные файлы находятся в правильно сформированном XML, вам будет гораздо лучше использовать реальный синтаксический анализатор (например, встроенный в JDK) для их синтаксического анализа, поскольку синтаксический анализатор обеспечит правильный перевод байтов в символы. Затем используйте выражение XPath для получения значений.
Если вы не использовали анализатор XML в прошлом, вот два документа, которые я написал о разборе и XPath.
Редактировать: одна вещь, которую вы можете найти полезной, это распечатать фактические значения символов в строке, используя что-то вроде следующего:
public static void main(String[] argv) throws Exception
{
String s = "testing\u20ac";
for (int ii = 0 ; ii < s.length() ; ii++)
{
System.out.println(ii + ": " + (int)s.charAt(ii) + " = " + s.charAt(ii));
}
}
Вам, вероятно, следует также распечатать ваш набор символов по умолчанию, чтобы вы знали, как любая конкретная последовательность байтов переводится в символы:
public static void main(String[] argv) throws Exception
{
System.out.println(Charset.defaultCharset());
}
И, наконец, вы должны проверить обслуживаемую страницу как необработанные байты, чтобы точно узнать, что возвращается клиенту.
Правка № 2: символ "Unicode" имеет значение 00F2, которое будет в кодировке UTF-8 как C3 B2. Эти два кода не соответствуют символам, которые вы указали в предыдущем ответе.
Дополнительные сведения о символах Unicode см. В таблицах кодов на Unicode.org.