класс 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 строки String может быть изменена двумя способами.
Во-первых, можно установить 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, Encoding.find(‘locale’)
Кодировка файловой системы
Кодировка по умолчанию для строк из файловой системы среды. Используется для строк имён или путей файлов.
см. Encoding.find(‘filesystem’)
Внешняя кодировка
Каждый объект IO имеет внешнюю кодировку, которая указывает кодировку, которую Ruby будет использовать для чтения данных. По умолчанию Ruby устанавливает внешнюю кодировку объекта IO на внешнюю кодировку по умолчанию. Внешняя кодировка по умолчанию устанавливается кодировкой локали или опцией интерпретатора -E. Encoding.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>
Внешнюю кодировку по умолчанию также можно установить с помощью Encoding.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. Encoding.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>]
Внутреннюю кодировку по умолчанию также можно установить с помощью Encoding.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();
GLOBAL_ENC_TABLE_EVAL(enc_table,
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-1968"=>"US-ASCII",
"SJIS"=>"Windows-31J", "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();
} Возвращает значение по умолчанию для внешней кодировки.
Внешняя кодировка по умолчанию используется по умолчанию для строк, созданных из следующих источников:
-
Fileданные, считанные с диска -
SDBM
Хотя строки, созданные из этих источников, будут иметь эту кодировку, кодировка может быть недействительной. Убедитесь, что проверили String#valid_encoding?.
File данные, записанные на диск, будут транскодированы во внешнюю кодировку по умолчанию при записи, если default_internal не равно nil.
Внешняя кодировка по умолчанию инициализируется опцией -E. Если -E не установлена, она инициализируется в UTF-8 в Windows и в соответствии с локалью на других операционных системах.
static VALUE
set_default_external(VALUE klass, VALUE encoding)
{
rb_warning("setting Encoding.default_external");
rb_enc_set_default_external(encoding);
return encoding;
} Устанавливает внешнюю кодировку по умолчанию. Не следует устанавливать Encoding::default_external в коде Ruby, так как строки, созданные до изменения значения, могут иметь другую кодировку, чем строки, созданные после изменения значения. Вместо этого используйте ruby -E для вызова Ruby с правильной внешней кодировкой по умолчанию.
См. Encoding::default_external для информации о том, как используется внешняя кодировка по умолчанию.
static VALUE
get_default_internal(VALUE klass)
{
return rb_enc_default_internal();
} Возвращает значение по умолчанию для внутренней кодировки. Строки будут транскодированы во внутреннюю кодировку по умолчанию в следующих местах, если внутренняя кодировка по умолчанию не равна nil:
-
Fileданные, считанные с диска -
Строки, возвращаемые из
Readline -
Строки, возвращаемые из SDBM
-
Значения из
ENV -
Значения в ARGV, включая $PROGRAM_NAME
Кроме того, String#encode и String#encode! используют внутреннюю кодировку по умолчанию, если кодировка не задана.
Кодировка скрипта (__ENCODING__), а не default_internal, используется в качестве кодировки созданных строк.
Encoding::default_internal инициализируется опцией -E или nil в противном случае.
static VALUE
set_default_internal(VALUE klass, VALUE encoding)
{
rb_warning("setting Encoding.default_internal");
rb_enc_set_default_internal(encoding);
return encoding;
} Устанавливает внутреннюю кодировку по умолчанию или удаляет её, если передано nil. Не следует устанавливать Encoding::default_internal в коде Ruby, так как строки, созданные до изменения значения, могут иметь другую кодировку, чем строки, созданные после изменения. Вместо этого следует использовать ruby -E для вызова Ruby с правильной внутренней кодировкой по умолчанию.
См. Encoding::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_VM_LOCK_ENTER();
{
rb_ary_replace(ary, rb_default_encoding_list);
rb_ary_concat(ary, rb_additional_encoding_list);
}
RB_VM_LOCK_LEAVE();
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"
Результат сильно зависит от платформы. Поэтому Encoding.find(Encoding.locale_charmap) может вызвать ошибку. Если вам нужен какой-либо объект кодировки даже для неизвестной локали, можно использовать Encoding.find («locale»).
static VALUE
rb_enc_name_list(VALUE klass)
{
VALUE ary;
GLOBAL_ENC_TABLE_ENTER(enc_table);
{
ary = rb_ary_new2(enc_table->names->num_entries);
st_foreach(enc_table->names, rb_enc_name_list_i, (st_data_t)ary);
}
GLOBAL_ENC_TABLE_LEAVE();
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 RBOOL(rb_enc_asciicompat(must_encoding(enc)));
} Возвращает, является ли кодировка ASCII-совместимой.
Encoding::UTF_8.ascii_compatible? #=> true Encoding::UTF_16BE.ascii_compatible? #=> false
static VALUE
enc_dummy_p(VALUE enc)
{
return RBOOL(ENC_DUMMY_P(must_encoding(enc)));
} Возвращает 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)" : ""),
rb_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_names(VALUE self)
{
VALUE args[2];
args[0] = (VALUE)rb_to_encoding_index(self);
args[1] = rb_ary_new2(0);
GLOBAL_ENC_TABLE_EVAL(enc_table,
st_foreach(enc_table->names, enc_names_i, (st_data_t)args));
return args[1];
} Возвращает список имен и псевдонимов кодировки.
Encoding::WINDOWS_31J.names #=> ["Windows-31J", "CP932", "csWindows31J", "SJIS", "PCK"]
static VALUE
enc_replicate_m(VALUE encoding, VALUE name)
{
int idx = rb_enc_replicate(name_for_encoding(&name), rb_to_encoding(encoding));
RB_GC_GUARD(name);
return rb_enc_from_encoding_index(idx);
} Возвращает дублированную кодировку 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–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.