класс 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 символами.
Изменение кодировки
Связанная Encoding строки может быть изменена двумя способами.
Во-первых, можно установить Encoding строки на новую Encoding, не изменяя внутреннего байтового представления строки, с помощью 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, которая будет связана с любой строкой-литералом, созданной в исходном коде.
По умолчанию кодировка сценария — Encoding::UTF-8 после версии 2.0, но её можно изменить с помощью магического комментария в первой строке файла исходного кода (или во второй строке, если в первой есть строка shebang). Комментарий должен содержать слово coding или encoding, за которым следует двоеточие, пробел и имя или псевдоним 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 или регулярных выражений.
Кодировка региональных параметров
Кодировка по умолчанию среды. Обычно выводится из региональных параметров.
см. Encoding.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)>]
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;
} Возвращает значение true, если кодировка совместима с ASCII, иначе — false.
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_usascii_str_new2(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_usascii_str_new2(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.