Книга: Программирование на языке Ruby

4.2.6. Преобразование из одной кодировки в другую

4.2.6. Преобразование из одной кодировки в другую

В стандартной библиотеке Ruby имеется интерфейс к библиотеке iconv для преобразования из одной кодировки символов в другую. Она должна работать на всех платформах, в том числе и в Windows (если дистрибутив устанавливался моментальным инсталлятором).

Чтобы преобразовать строку из UTF-8 в ISO-8859-15, библиотека iconv используется следующим образом:

require 'iconv'
converter = Iconv.new('ISO-8859-15', 'UTF-8')
sword_iso = converter.iconv(sword)

Важно помнить, что сначала указывается целевая кодировка, а потом исходная (как при присваивании). Количество и названия поддерживаемых кодировок зависят от платформы, но наиболее распространенные стандартизованы и имеются везде. Если установлена пакетная утилита iconv, то перечень распознаваемых кодировок можно получить с помощью команды iconv -l.

Помимо названия кодировки, iconv принимает еще флаги, управляющие ее поведением. Они указываются в конце строки, содержащей целевую кодировку.

Обычно iconv возбуждает исключение, если получает недопустимые входные данные или почему-либо не может представить их в целевой кодировке. Флаг //IGNORE подавляет исключение.

broken_utf8_string = "helloxfe"
converter = Iconv.new('ISO-8859-15', 'UTF-8')
# будет возбуждено исключение Iconv::IllegalSequence
converter.iconv(broken_utf8_string)
converter = Iconv.new('ISO-8859-15//IGNORE', 'UTF-8')
converter.iconv(broken_utf8_string) # "hello"

Этот же флаг позволяет очистить строку от неверных данных:

broken_sword = "?p?exfe"
converter = Iconv.new('UTF-8//IGNORE', 'UTF-8')
converter.iconv(broken_sword) # "?p?e"

Иногда некоторые символы нельзя представить в целевой кодировке. Обычно в этом случае возбуждается исключение. Флаг //TRANSLIT говорит iconv, что нужно вместо этого попытаться подобрать приблизительные эквиваленты.

converter = Iconv.new('ASCII', 'UTF-8')
converter.iconv(sword) # Возбуждается Iconv::IllegalSequence.
converter = Iconv.new('ASCII//IGNORE', 'UTF-8')
converter.iconv(sword) # "pe"
converter = Iconv.new('ASCII//TRANSLIT', 'UTF-8')
converter.iconv(sword) # "'ep'ee"

Этим свойством можно воспользоваться, чтобы получить URL, содержащий только ASCII-символы:

str = "Stra?e ?p?e"
converter = Iconv.new('ASCII//TRANSLIT', 'UTF-8')
converter.iconv(sword).gsub(/ /, '-').gsub(/[^а-z-]/in).downcase
# "strasse-epee"

Однако работать это будет лишь в отношении латиницы. В листинге 4.2 приведен реальный пример совместного применения библиотек iconv и open-uri для скачивания Web-страницы и перекодирования ее в UTF-8.

Листинг 4.2. Перекодирование Web-страницы в кодировку UTF-8

require 'open-uri'
require 'iconv'
def get_web_page_as_utf8(url)
 open(url) do |io|
  source = io.read
  type, *parameters = io.content_type_parse
  # He перекодировать, если не (X)HTML
  unless type =~ %r!^(?:text/html|application/xhtml+xml)$!
   return source
  end
  # Сначала проверяем заголовки, присланные сервером:
  if pair = parameters.assoc('charset')
   encoding = pair.last
   # Затем анализируем HTML:
  elsif source =~ ?]*?charset=([^s'"]+)/i
   encoding = $1
   # Если не удалось определить, предполагаем кодировку по умолчанию,
   # определенную в стандарте HTTP.
  else
   encoding = 'ISO-8859-1'
  end
  converter = Iconv.new('UTF-8//IGNORE', encoding)
  return converter.iconv(source)
 end
end

Это еще не все системные вопросы, связанные с преобразованием кодировок. Предположим, что в операционной системе, где установлен Ruby, определена локаль, отличная от UTF-8, или Ruby общается с ОС не в UTF-8 (так, например, обстоит дело в дистрибутиве для Win32). Тогда возникают дополнительные сложности.

Например, Windows поддерживает Unicode в именах файлов и на системном уровне работает исключительно в Unicode. Но в настоящее время Ruby взаимодействует с Windows при помощи устаревших кодовых страниц. Для англоязычного и большинства других западных изданий это страница 1252 (или WINDOWS-1252).

Внутри программы можно пользоваться и кодировкой UTF-8, но все имена файлов придется перевести в кодировку, заданную кодовой страницей. Iconv поможет это сделать, но важно не забывать, что кодовая страница позволяет описать только малое подмножество всех символов, имеющихся в Unicode.

Кроме того, это означает, что пока Ruby для Windows не может открывать файлы, имена которых нельзя описать с помощью кодовой страницы. Это ограничение не относится к Mac OS X, Linux и другим системам с локалью UTF-8.

Оглавление книги


Генерация: 1.416. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз