Pull to refresh

Кодировки и веб-страницы

Reading time 4 min
Views 30K
Возвращаясь к избитой проблеме с кодировками русских букв, хотелось бы иметь под рукой некий единый справочник или руководство, в котором можно найти решения различных сходных ситуаций. В своё время сам перелопатил множество статей и публикаций, чтобы находить причины ошибок. Задача этой публикации — сэкономить время и нервы читателя и собрать воедино различные причины ошибок с кодировками в разработке на Java и JSP и способы их устранения.

Варианты решения могут быть не единственными, охотно добавлю предложенные читателем, если они будут рабочими.

Итак, поехали.

1. Проблема: при получении разработанной мной страницы браузером весь русский текст идёт краказябрами, даже тот, который забит статически.
Причина: браузер неверно определяет кодировку текста, потому что нет явного указания.
Решение: явно указать кодировку:
a) HTML: добавляем тэг META в хидер страницы:
[\< meta http-equiv="Content-Type" content="text/html; charset=cp1251"\>]

б) XML: указываем кодировку в заголовке:
[<?xml version="1.0" encoding="cp1251"?>]

в) JSP — задаём тип контента в заголовке:
[<%@ page language="java" contentType="text/html;charset=cp1251"%>]

г) JSP — задаём кодировку возвращаемой страницы
[<%@ page pageEncoding="cp1251"%>]

д) Java — устанавливаем хидер ответа:
[response.setCharacterEncoding("cp1251");]
[response.setContentType("text/html;charset=cp1251");]


2. Проблема: написанный в JSP-странице статический русский текст почему-то идёт краказабрами, хотя кодировка страницы задана.
Причина: статический текст был написан в кодировке, отличной от заданного странице.
Решение: изменить кодировку в редакторе (например, для AkelPad нажимаем «Сохранить как» и выбираем нужную кодировку).

3. Проблема: получаемый из запроса текст идёт кракозябрами.
Причина: кодировка запроса отличается от используемой для его обработки кодировки.
Решение: установить кодировку запроса или перекодировать в нужную.
а) Java, со стороны отправителя не задана нужная кодировка — перекодируем в нужную:
[String MyParam= new String(request.getParameter("MyParam").getBytes("ISO-8859-1"),"cp1251");]

Примечание: кодировка ISO-8859-1 устанавливается по умолчанию, если не была задана другая.
б) Java, со стороны отправителя задана нужная кодировка — устанавливаем кодировку запроса:
[request.setCharacterEncoding("cp1251");]


4. Проблема: отправленный GET-параметром русский текст при редиректе приходит кракозябрами.
Причина: упаковка русского текста в URI по умолчанию идёт в ISO-8859-1.
Решение: упаковать текст в нужной кодировке вручную.
а) JSP, URLEncoder:
[<%@ page import="java.net.URLEncoder"%>
<%response.sendRedirect("targetPage.jsp?MyParam="+URLEncoder.encode("Русский текст","cp1251"));%>]


5. Проблема: текст из базы данных читается кракозябрами.
Причина: кодировка текста, прочитанного из базы данных, отличается от кодировки страницы.
Решение: установить соответствующую кодировку страницы, либо перекодировать полученные из базы данных значения.
а) Java, перекодирование считанной в db_string базы данных строки:
[String MyValue = new String(db_string.getBytes("utf-8"),"cp1251");]


6. Проблема: текст записывается в базу данных кракозябрами, хотя на странице отображается правильно.
Причина: кодировка записываемой строки отличается от кодировки сессии работы с базой данных, либо от кодировки базы данных (стоит помнить, что они не всегда совпадают).
Решение: установить необходимую кодировку сессии или перекодировать строку.
а) Java, перекодирование записываемой строки db_string в кодировку сессии или базы данных:
[String db_string = new String(MyValue.getBytes("cp1251"),"utf-8");]

б) Java, MySQL, настройка параметров подключения в строке dburl, передаваемой функции коннекта:
[dburl += "?characterEncoding=cp1251";]

в) MySQL, настройка параметров подключения в XML-описателе контекста, добавляем атрибут к тегу \<Resource\>:
[connectionProperties="useUnicode=no;characterEncoding=cp1251;"]

г) MySQL, прямая установка кодировки сессии вызовом SET NAMES (connect — объект подключения Connection):
[CallableStatement cs = connect.prepareCall("set names 'cp1251'");
cs.execute();]


7. Проблема: если ничего не помогло…
Решение: всегда остаётся самый «топорный» метод — прямое перекодирование.
а) Для известной кодировки источника:
[String MyValue = new String(source_string.getBytes("utf-8"),"cp1251");]

б) Для параметра запроса:
[String MyValue = new String(request.getParameter("MyParam").getBytes(request.getCharacterEncoding()),"cp1251");]


Дополнение, или что нужно знать:

1. Кодировки базы данных и сессии подключения могут различаться, в зависимости от конкретной СУБД и драйвера. К примеру, при подключении к MySQL стандартным драйвером com.mysql.jdbc.Driver без явного указания кодировка сессии устанавливалась в UTF-8, несмотря на другую кодировку схемы БД.
2. Кодировка упаковки строки запроса в URI по умолчанию устанавливается в ISO-8859-1. С подобным можно столкнуться, например, при передаче явно заданного текста в редиректе с одной страницы на другую.
3. Взаимоотношения кодировок страницы, базы данных, сессии, параметров запроса и ответа не зависят от языка разработки и описанные для Java функции имеют аналоги для PHP, Asp и других.

Примечание: восстановить ссылки на источники нет возможности, все примеры взяты из собственного кода, хотя когда-то так же выискивал их по многочисленным форумам.

Надеюсь, этот небольшой обзор поможет начинающим веб-программистам сократить время отладки и сберечь нервы.
Tags:
Hubs:
-5
Comments 17
Comments Comments 17

Articles