класс Encoding
Экземпляр Encoding представляет кодировку символов, используемую в Ruby. Он определяется как константа в пространстве имен Encoding. У него есть имя и необязательно, псевдонимы:
Encoding::ISO_8859_1.name #=> "ISO-8859-1" Encoding::ISO_8859_1.names #=> ["ISO-8859-1", "ISO8859-1"]
Методы Ruby, работающие с кодировками, возвращают или принимают экземпляры Encoding в качестве аргументов (когда метод принимает экземпляр Encoding в качестве аргумента, можно передать вместо него имя или псевдоним Encoding).
"some string".encoding #=> #<Encoding:UTF-8> string = "some string".encode(Encoding::ISO_8859_1) #=> "some string" string.encoding #=> #<Encoding:ISO-8859-1> "some string".encode "ISO-8859-1" #=> "some string"
Encoding::ASCII_8BIT — это специальная кодировка, обычно используемая для строковых байтов, а не для строковых символов. Но, как следует из названия, ее символы в диапазоне ASCII считаются символами ASCII. Это полезно, когда вы используете символы ASCII-8BIT с другими совместимыми с ASCII символами.
Изменение кодировки
Связанная кодировка строки может быть изменена двумя способами.
Во-первых, можно установить кодировку строки на новую кодировку без изменения внутреннего байтового представления строки с помощью String#force_encoding. Это то, как вы можете сообщить Ruby правильную кодировку строки.
string #=> "R\xC3\xA9sum\xC3\xA9" string.encoding #=> #<Encoding:ISO-8859-1> string.force_encoding(Encoding::UTF_8) #=> "R\u00E9sum\u00E9"
Во-вторых, можно перекодировать строку, т.е. преобразовать ее внутреннее байтовое представление в другую кодировку. Ее связанная кодировка также устанавливается на другую кодировку. См. String#encode для различных форм перекодирования и класс Encoding::Converter для дополнительного управления процессом перекодирования.
string #=> "R\u00E9sum\u00E9" string.encoding #=> #<Encoding:UTF-8> string = string.encode!(Encoding::ISO_8859_1) #=> "R\xE9sum\xE9" string.encoding #=> #<Encoding::ISO-8859-1>
Кодировка скрипта
У всего кода скрипта Ruby есть связанная кодировка, которая будет связана с любой строкой-литералом, созданной в исходном коде.
По умолчанию кодировка скрипта составляет Encoding::UTF-8 после версии 2.0, но ее можно изменить с помощью магического комментария в первой строке файла исходного кода (или во второй, если в первой есть строка shebang). Комментарий должен содержать слово coding или encoding, за которым следует двоеточие, пробел и имя или псевдоним кодировки:
# encoding: UTF-8 "some string".encoding #=> #<Encoding:UTF-8>
Ключевое слово __ENCODING__ возвращает кодировку скрипта файла, в котором оно написано:
# encoding: ISO-8859-1 __ENCODING__ #=> #<Encoding:ISO-8859-1>
ruby -K изменит кодировку по умолчанию, но это не рекомендуется. Файлы исходного кода Ruby должны объявлять свою кодировку скрипта с помощью магического комментария, даже если они зависят только от строк US-ASCII или регулярных выражений.
Локальная кодировка
Кодировка по умолчанию среды. Обычно извлекается из локали.
см. ::locale_charmap, ::find('locale')
Кодировка файловой системы
Кодировка по умолчанию для строк из файловой системы среды. Используется для строк имен файлов или путей.
см. ::find('filesystem')
Внешняя кодировка
Каждый объект IO имеет внешнюю кодировку, которая указывает кодировку, которую Ruby будет использовать для чтения данных. По умолчанию Ruby устанавливает внешнюю кодировку объекта IO на кодировку по умолчанию. Кодировка по умолчанию определяется кодировкой локали или интерпретатором -E параметром. ::default_external возвращает текущее значение внешней кодировки.
ENV["LANG"] #=> "UTF-8" Encoding.default_external #=> #<Encoding:UTF-8> $ ruby -E ISO-8859-1 -e "p Encoding.default_external" #<Encoding:ISO-8859-1> $ LANG=C ruby -e 'p Encoding.default_external' #<Encoding:US-ASCII>
Внешняя кодировка по умолчанию также может быть установлена с помощью ::default_external=, но этого делать не следует, так как у строк, созданных до и после изменения, будут несовместимые кодировки. Вместо этого используйте ruby -E для вызова ruby с правильной внешней кодировкой.
Если вам известно, что фактическая кодировка данных объекта IO отличается от внешней кодировки по умолчанию, вы можете сбросить ее внешнюю кодировку с помощью IO#set_encoding или установить ее при создании объекта IO (см. параметры IO.new).
Внутренняя кодировка
Для обработки данных объекта IO, имеющего кодировку, отличную от внешней кодировки, можно установить его внутреннюю кодировку. Ruby будет использовать эту внутреннюю кодировку для перекодирования данных при чтении из объекта IO.
Обратно, при записи данных в объект IO они перекодируются из внутренней кодировки во внешнюю кодировку объекта IO.
Внутренняя кодировка объекта IO может быть установлена с помощью IO#set_encoding или при создании объекта IO (см. параметры IO.new).
Внутренняя кодировка необязательна, и когда она не установлена, используется кодировка по умолчанию Ruby. Если не указано явно, эта кодировка по умолчанию — nil, что означает, что по умолчанию перекодирование не происходит.
Кодировка по умолчанию может быть установлена с помощью параметра интерпретатора -E. ::default_internal возвращает текущую внутреннюю кодировку.
$ ruby -e 'p Encoding.default_internal' nil $ ruby -E ISO-8859-1:UTF-8 -e "p [Encoding.default_external, \ Encoding.default_internal]" [#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>]
Кодировка по умолчанию также может быть установлена с помощью ::default_internal=, но этого делать не следует, так как у строк, созданных до и после изменения, будут несовместимые кодировки. Вместо этого используйте ruby -E для вызова ruby с правильной внутренней кодировкой.
Пример кодировки IO
В следующем примере строка «Ru00E9sumu00E9» с кодировкой UTF-8 перекодируется для вывода в кодировку ISO-8859-1, затем считывается обратно и перекодируется в UTF-8:
string = "R\u00E9sum\u00E9"
open("transcoded.txt", "w:ISO-8859-1") do |io|
io.write(string)
end
puts "raw text:"
p File.binread("transcoded.txt")
puts
open("transcoded.txt", "r:ISO-8859-1:UTF-8") do |io|
puts "transcoded text:"
p io.read
end
При записи файла внутренняя кодировка не задана, так как она необходима только для чтения. При чтении файла необходимо указать как внутреннюю, так и внешнюю кодировку, чтобы получить правильный результат.
$ ruby t.rb raw text: "R\xE9sum\xE9" transcoded text: "R\u00E9sum\u00E9"
Методы публичного класса
static VALUE
rb_enc_aliases(VALUE klass)
{
VALUE aliases[2];
aliases[0] = rb_hash_new();
aliases[1] = rb_ary_new();
st_foreach(enc_table.names, rb_enc_aliases_enc_i, (st_data_t)aliases);
return aliases[0];
} Возвращает хеш доступных псевдонимов кодировки и оригинальных имён кодировки.
Encoding.aliases
#=> {"BINARY"=>"ASCII-8BIT", "ASCII"=>"US-ASCII", "ANSI_X3.4-1986"=>"US-ASCII",
"SJIS"=>"Shift_JIS", "eucJP"=>"EUC-JP", "CP932"=>"Windows-31J"} static VALUE
enc_compatible_p(VALUE klass, VALUE str1, VALUE str2)
{
rb_encoding *enc;
if (!enc_capable(str1)) return Qnil;
if (!enc_capable(str2)) return Qnil;
enc = rb_enc_compatible(str1, str2);
if (!enc) return Qnil;
return rb_enc_from_encoding(enc);
} Проверяет совместимость двух объектов.
Если оба объекта являются строками, они совместимы, если их можно конкатенировать. Кодировка конкатенированной строки возвращается, если они совместимы, и nil, если нет.
Encoding.compatible?("\xa1".force_encoding("iso-8859-1"), "b")
#=> #<Encoding:ISO-8859-1>
Encoding.compatible?(
"\xa1".force_encoding("iso-8859-1"),
"\xa1\xa1".force_encoding("euc-jp"))
#=> nil
Если объекты не являются строками, их кодировки совместимы, если у них есть кодировка и:
-
Любая из кодировок совместима с US-ASCII
-
Одна из кодировок является 7-битной кодировкой
static VALUE
get_default_external(VALUE klass)
{
return rb_enc_default_external();
} Возвращает кодировку по умолчанию для внешних данных.
Кодировка по умолчанию для внешних данных используется по умолчанию для строк, созданных из следующих источников:
-
Данные из файла, считанные с диска
Хотя строки, созданные из этих источников, будут иметь эту кодировку, кодировка может быть неверной. Убедитесь, что проверили String#valid_encoding?.
Данные файла, записанные на диск, будут преобразованы в кодировку по умолчанию для внешних данных при записи.
Кодировка по умолчанию для внешних данных инициализируется языковым окружением или опцией -E.
static VALUE
set_default_external(VALUE klass, VALUE encoding)
{
rb_warning("setting Encoding.default_external");
rb_enc_set_default_external(encoding);
return encoding;
} Устанавливает кодировку по умолчанию для внешних данных. Не следует устанавливать ::default_external в коде Ruby, так как строки, созданные до изменения значения, могут иметь другую кодировку, чем строки, созданные после изменения значения. Вместо этого следует использовать ruby -E для вызова Ruby с правильной кодировкой по умолчанию для внешних данных.
См. ::default_external для получения информации о том, как используется кодировка по умолчанию для внешних данных.
static VALUE
get_default_internal(VALUE klass)
{
return rb_enc_default_internal();
} Возвращает кодировку по умолчанию для внутренних данных. Строки будут преобразованы в кодировку по умолчанию для внутренних данных в следующих случаях, если кодировка по умолчанию для внутренних данных не равна nil:
-
Данные из файла, считанные с диска
-
Имена файлов из Dir
-
Строки, возвращаемые из Readline
-
Строки, возвращаемые из SDBM
-
Значения из ENV
-
Значения в ARGV, включая $PROGRAM_NAME
Кроме того, String#encode и String#encode! используют кодировку по умолчанию для внутренних данных, если кодировка не указана.
Кодировка среды (__ENCODING__), а не ::default_internal, используется в качестве кодировки созданных строк.
::default_internal инициализируется кодировкой внутреннего файла или опцией -E.
static VALUE
set_default_internal(VALUE klass, VALUE encoding)
{
rb_warning("setting Encoding.default_internal");
rb_enc_set_default_internal(encoding);
return encoding;
} Устанавливает кодировку по умолчанию для внутренних данных или удаляет кодировку по умолчанию для внутренних данных, если передано значение nil. Не следует устанавливать ::default_internal в коде Ruby, так как строки, созданные до изменения значения, могут иметь другую кодировку, чем строки, созданные после изменения. Вместо этого следует использовать ruby -E для вызова Ruby с правильной кодировкой по умолчанию для внутренних данных.
См. ::default_internal для получения информации о том, как используется кодировка по умолчанию для внутренних данных.
static VALUE
enc_find(VALUE klass, VALUE enc)
{
int idx;
if (is_obj_encoding(enc))
return enc;
idx = str_to_encindex(enc);
if (idx == UNSPECIFIED_ENCODING) return Qnil;
return rb_enc_from_encoding_index(idx);
} Поиск кодировки по указанному имени. имя должно быть строкой.
Encoding.find("US-ASCII") #=> #<Encoding:US-ASCII>
Имена, которые принимает этот метод, — это имена кодировок и псевдонимы, включая следующие специальные псевдонимы:
- “external”
-
кодировка по умолчанию для внешних данных
- “internal”
-
кодировка по умолчанию для внутренних данных
- “locale”
-
кодировка среды
- “filesystem”
-
кодировка файловой системы
Если кодировка с указанным именем не найдена, генерируется исключение ArgumentError. Только Encoding.find("internal") возвращает nil, если кодировка с именем “internal” не найдена, то есть если у Ruby нет кодировки по умолчанию для внутренних данных.
static VALUE
enc_list(VALUE klass)
{
VALUE ary = rb_ary_new2(0);
rb_ary_replace(ary, rb_encoding_list);
return ary;
} Возвращает список загруженных кодировок.
Encoding.list
#=> [#<Encoding:ASCII-8BIT>, #<Encoding:UTF-8>,
#<Encoding:ISO-2022-JP (dummy)>]
Encoding.find("US-ASCII")
#=> #<Encoding:US-ASCII>
Encoding.list
#=> [#<Encoding:ASCII-8BIT>, #<Encoding:UTF-8>,
#<Encoding:US-ASCII>, #<Encoding:ISO-2022-JP (dummy)>]
VALUE
rb_locale_charmap(VALUE klass)
{
#if NO_LOCALE_CHARMAP
return rb_usascii_str_new_cstr("US-ASCII");
#else
return locale_charmap(rb_usascii_str_new_cstr);
#endif
} Возвращает имя набора символов среды. Возвращает nil, если соответствующая информация отсутствует.
Debian GNU/Linux
LANG=C
Encoding.locale_charmap #=> "ANSI_X3.4-1968"
LANG=ja_JP.EUC-JP
Encoding.locale_charmap #=> "EUC-JP"
SunOS 5
LANG=C
Encoding.locale_charmap #=> "646"
LANG=ja
Encoding.locale_charmap #=> "eucJP"
Результат сильно зависит от платформы. Поэтому ::find может привести к ошибке. Если вам нужен какой-либо объект кодировки даже для неизвестной среды, можно использовать ::find(“locale”).
static VALUE
rb_enc_name_list(VALUE klass)
{
VALUE ary = rb_ary_new2(enc_table.names->num_entries);
st_foreach(enc_table.names, rb_enc_name_list_i, (st_data_t)ary);
return ary;
} Возвращает список доступных имён кодировок.
Encoding.name_list
#=> ["US-ASCII", "ASCII-8BIT", "UTF-8",
"ISO-8859-1", "Shift_JIS", "EUC-JP",
"Windows-31J",
"BINARY", "CP932", "eucJP"] Общедоступные методы экземпляров
static VALUE
enc_ascii_compatible_p(VALUE enc)
{
return rb_enc_asciicompat(must_encoding(enc)) ? Qtrue : Qfalse;
} Возвращает, является ли кодировка ASCII-совместимой.
Encoding::UTF_8.ascii_compatible? #=> true Encoding::UTF_16BE.ascii_compatible? #=> false
static VALUE
enc_dummy_p(VALUE enc)
{
return ENC_DUMMY_P(must_encoding(enc)) ? Qtrue : Qfalse;
} Возвращает true для фиктивных кодировок. Фиктивная кодировка — это кодировка, для которой обработка символов не реализована должным образом. Она используется для состоятельных кодировок.
Encoding::ISO_2022_JP.dummy? #=> true Encoding::UTF_8.dummy? #=> false
static VALUE
enc_inspect(VALUE self)
{
rb_encoding *enc;
if (!is_data_encoding(self)) {
not_encoding(self);
}
if (!(enc = DATA_PTR(self)) || rb_enc_from_index(rb_enc_to_index(enc)) != enc) {
rb_raise(rb_eTypeError, "broken Encoding");
}
return rb_enc_sprintf(rb_usascii_encoding(),
"#<%"PRIsVALUE":%s%s%s>", rb_obj_class(self),
rb_enc_name(enc),
(ENC_DUMMY_P(enc) ? " (dummy)" : ""),
enc_autoload_p(enc) ? " (autoload)" : "");
} Возвращает строку, представляющую кодировку для программистов.
Encoding::UTF_8.inspect #=> "#<Encoding:UTF-8>" Encoding::ISO_2022_JP.inspect #=> "#<Encoding:ISO-2022-JP (dummy)>"
static VALUE
enc_name(VALUE self)
{
return rb_fstring_cstr(rb_enc_name((rb_encoding*)DATA_PTR(self)));
} Возвращает имя кодировки.
Encoding::UTF_8.name #=> "UTF-8"
static VALUE
enc_names(VALUE self)
{
VALUE args[2];
args[0] = (VALUE)rb_to_encoding_index(self);
args[1] = rb_ary_new2(0);
st_foreach(enc_table.names, enc_names_i, (st_data_t)args);
return args[1];
} Возвращает список имени и псевдонимов кодировки.
Encoding::WINDOWS_31J.names #=> ["Windows-31J", "CP932", "csWindows31J"]
static VALUE
enc_replicate(VALUE encoding, VALUE name)
{
return rb_enc_from_encoding_index(
rb_enc_replicate(StringValueCStr(name),
rb_to_encoding(encoding)));
} Возвращает скопированную кодировку enc с именем name. Новая кодировка должна иметь ту же структуру байтов, что и enc. Если name используется другой кодировкой, вызовите ArgumentError.
static VALUE
enc_name(VALUE self)
{
return rb_fstring_cstr(rb_enc_name((rb_encoding*)DATA_PTR(self)));
} Возвращает имя кодировки.
Encoding::UTF_8.name #=> "UTF-8"
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.