Неверные строки UTF-8 Ruby - PullRequest
1 голос
/ 14 марта 2019

Я сталкиваюсь с некоторым странным поведением и несогласованностью в том, как Ruby (v2.5.3) работает с закодированными строками по сравнению с синтаксическим анализатором YAML.Вот пример:

"\x80"          # Returns "\x80"
"\x80".bytesize # Returns 1
"\x80".bytes    # Returns [128]
"\x80".encoding # Returns UTF-8

YAML.load('{value: "\x80"}')["value"]          # Returns "\u0080"
YAML.load('{value: "\x80"}')["value"].bytesize # Returns 2
YAML.load('{value: "\x80"}')["value"].bytes    # Returns [194, 128]
YAML.load('{value: "\x80"}')["value"].encoding # Returns UTF-8

Мое понимание UTF-8 состоит в том, что любое однобайтовое значение выше 0x7F должно быть закодировано в два байта.Поэтому у меня следующие вопросы:

  1. Является ли однобайтовая строка "\x80" допустимым UTF-8?
  2. Если так, почему YAML преобразуется в двухбайтовый шаблон?
  3. Если нет, то почему Ruby утверждает, что кодировка UTF-8, но содержит недопустимую последовательность байтов?
  4. Есть ли способ заставить синтаксический анализатор YAML и строку Ruby вести себя одинаковокак друг друга?

1 Ответ

3 голосов
/ 15 марта 2019

Недопустимо UTF-8

"\x80".valid_encoding?
# false

Ruby утверждает, что это UTF-8, потому что все строковые литералы по умолчанию имеют UTF-8, даже если это делает их недействительными.

Я не думаю, что вы можете заставить анализатор YAML возвращать неверный UTF-8.Но чтобы заставить Ruby конвертировать этого персонажа, вы можете сделать это

"\x80".b.ord.chr('utf-8')
# "\u0080"

.b только в Ruby 2+.Вы должны использовать force_encoding в противном случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...