=encoding UTF-8

=head1 NAME/НАИМЕНОВАНИЕ

perlunitut - Учебник по Юникоду в Perl

=head1 ОПИСАНИЕ

Дни простой обработки строк закончились. Установлено, что
современные программы должны быть способны общаться смешанными акцентированными буквами и
такими вещами, как символы евро. Это означает, что программистам нужны новые привычки. 
Легко программировать Юникодо-совместимое программное обеспечение, но для этого требуется дисциплина, чтобы делать
 это правильно.

Существует много знаний о наборах символов и кодировках текста. Вероятно,
лучше всего провести целый день для их изучения, но основы могут быть изучены за минуты.

Это вообще-то не самые основы. Предполагается, что вы уже
знаете разницу между байтом и символом и понимаете (и принимаете!),
что существует много различных наборов символов и кодировок и, что ваша
Программа должна четко знать о них. Рекомендуется для чтения  
L<Абсолютный Минимум, который Каждый Разработчик Программного Обеспечения Обязательно Должен Знать о Unicode и Наборах Символов|http://local.joelonsoftware.com/wiki/%D0%90%D0%B1%D1%81%D0%BE%D0%BB%D1%8E%D1%82%D0%BD%D1%8B%D0%B9_%D0%9C%D0%B8%D0%BD%D0%B8%D0%BC%D1%83%D0%BC,_%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D0%B9_%D0%9A%D0%B0%D0%B6%D0%B4%D1%8B%D0%B9_%D0%A0%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA_%D0%9F%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%9E%D0%B1%D0%B5%D1%81%D0%BF%D0%B5%D1%87%D0%B5%D0%BD%D0%B8%D1%8F_%D0%9E%D0%B1%D1%8F%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE_%D0%94%D0%BE%D0%BB%D0%B6%D0%B5%D0%BD_%D0%97%D0%BD%D0%B0%D1%82%D1%8C_%D0%BE_Unicode_%D0%B8_%D0%9D%D0%B0%D0%B1%D0%BE%D1%80%D0%B0%D1%85_%D0%A1%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB%D0%BE%D0%B2>
 Джоэла Спольски , оригинал на английском
L<The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)|http://joelonsoftware.com/articles/Unicode.html>.

Этот учебник говорит о довольно абсолютных терминах и предоставляет лишь ограниченное представление
о богатстве функций обработки символов, которые Perl может предложить. Для
большинства проектов этой информации, вероятно, будет достаточно.

=head2 Определения

Важно, чтобы мы установили сначала  несколько вещей. Это самая важная
часть этого учебника. Эта точка зрения может конфликтовать с другой информацией, что вы
возможно, нашли в Интернете, но это главным образом потому, что многие источники неправильны.

Возможно, вам придется перечитать этот весь раздел несколько раз...

=head3 Юникод

B<Юникод>— это набор символов с дополнительным окном для всех символов. Порядковый номер
 символа называется B<кодовой точкой>. (Но на практике,
стирается различие между кодовой точкой и символом, так что термины часто
используются как синонимы.)

Есть многие, многие кодовые точки, но компьютеры работают с байтами и байт имеет
окно только для только 256 значений. Юникод имеет намного больше символов, чем это,
так что вам нужен метод, чтобы сделать их доступными.

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

=head3 UTF-8

B<UTF-8> это Юникодная кодировка. Многие люди думают, что Юникод и UTF-8
- это одно и то же, но это не так. Есть много Юникодных кодировок, но большая часть
мира стандартизирована под UTF-8.

UTF-8 рассматривает первые 128 кодовых точек, 0..127, так же, как ASCII. Она принимает
только один байт на символ. Все остальные символы кодируются как два или более (до шести) байт,
используя сложную схему. К счастью Perl обрабатывает это для
нас, поэтому мы не должны беспокоиться об этом.

=head3 Текстовые строки (строки символов)

B<Текстовые строки>, или B<символьные строки> изготовлены из символов. Байт
здесь не имеет значения, а только кодировка. Каждый символ это просто символ.

С текстовой строкой вы можете делать такие вещи:

    $text =~ s/foo/bar/;
    if ($string =~ /^\d+$/) { ... }
    $text = ucfirst $text;
    my $character_count = length $text;

Значение соответствующего кода символа (C<ord>, C<chr>) связано с Юникодной кодовой точкой.

=head3 Двоичные строки (строки байтов)

B<Двоичные строки>, или B<строки байтов> изготовлены из байтов. Здесь вы не имеете
символов, просто байты. Все коммуникации с внешним миром (что-либо
за пределами вашего текущего процесса Perl) делаются в двоичном виде.

С двоичной строкой вы могли бы сделать такие вещи, как:

    my (@length_content) = unpack "(V/a)*", $binary;
    $binary =~ s/\x00\x0F/\xFF\xF0/;  # для смелых :)
    print {$fh} $binary;
    my $byte_count = length $binary;

=head3 Кодирование (Encoding)

B<Кодирование> (как глагол) является преобразованием от I<текста> к I<двоичным данным>. Для кодирования,
вы должны указать целевую кодировку, например C<iso-8859-1> или C<UTF-8>.
Некоторые кодировки такие, как C<iso-8859> ("латинский") диапазон, не поддерживают полный
стандарт Юникода; символы, которые не могут быть представлены теряются во время
преобразования.

=head3 Декодирование (Decoding)

B<Декодирование> является преобразованием от I<двоичного формата> к I<тексту>. 
Чтобы декодировать, вы должны знать, какая кодировка используется на этапе кодирования.
И самое главное это должно быть что-то что поддается декодированию.
Не будет большого смысла для декодирования изображения в формате PNG в текстовую строку.

=head3 Внутренний формат

Perl имеет B<внутренний формат> (B<internal format>), кодирования, который он использует для кодирования текстовых строк
так, что он их может хранить в памяти. Все текстовые строки находятся в этом внутреннем формате.
В самом деле текстовые строки никогда не бывают в любом другом формате!

Вы не должны беспокоиться о том, что это за формат, потому что преобразование
автоматически делается, когда вы декодируете или кодируете.

=head2 Ваш новый инструментарий

Добавьте в ваш стандартный заголовок следующую строку:

    use Encode qw(encode decode);

Или, если вы ленивы, просто:

    use Encode;

=head2 Поток ввода-вывода (I/O flow) (фактические 5 минутный учебник)

Типичный поток ввода-вывода программы состоит из:

    1. Получение и декодирование (Receive and decode)
    2. Процесс (Process)
    3. Кодирование и вывод (Encode and output)

Если ваши входящие данные являются двоичными, то они и должны оставаться двоичными, вы не должны декодировать
их в текстовую строку, конечно. Но, во всех остальных случаях, вы должны их декодировать.

Декодирование не может произойти надежно, если вы не знаете как закодированы данные. Если
вы можете выбрать, то хорошей идеей будет сделать стандартом UTF-8.

    my $foo   = decode('UTF-8', get 'http://example.com/');
    my $bar   = decode('ISO-8859-1', readline STDIN);
    my $xyzzy = decode('Windows-1251', $cgi->param('foo'));

Обработка происходит также, как вы знали раньше. Единственное различие заключается в том, что сейчас
вы используете символы вместо байт. Это очень полезно, когда вы используете такие функции, как
C<substr>, или C<length>.

Важно понимать, что у нас нет байт в текстовой строке. Конечно
Perl имеет свою внутреннюю кодировку для хранения строк в памяти, но нужно игнорировать это.
Если вам нужно сделать что-нибудь байтами, то, вероятно, лучше сделать эту часть это сделать на
 шаге 3, только после того, как вы закодируете строки. Тогда вы знаете
точно сколько байт будет в строке назначения.

Синтаксис для кодирования строк текста в двоичные строки также прост, как и для декодирования:

    $body = encode('UTF-8', $body);

Если вам необходимо знать длину строки в байтах, теперь пришло идеальное время
для этого. Потому что C<$body> теперь строка байтов и C<length> сообщит 
 число байт, а не число знаков. Число символов
 больше не известно, потому что символы существуют только в текстовых строк.

    my $byte_count = length $body;

И, если вы используете протокол, который поддерживает способ дать получателем информацию,
какие кодировки символов вы использовали, пожалуйста, помогите принимающей стороне, используя эту возможность!
 Например, электронная почта (E-mail) и HTTP поддерживают MIME-заголовки, поэтому вы можете использовать
заголовок C<Content-Type>. Они также могут иметь C<Content-Length> для обозначения
числа I<байт>, так что это всегда хорошая идея указать его, если это число известно.

    "Content-Type: text/plain; charset=UTF-8",
    "Content-Length: $byte_count"

=head1 РЕЗЮМЕ

Декодируйте все, что вы получаете, кодируйте все, что вы посылаете. (Если это текстовые
данные.)

=head1 В и О (или ВИО) Вопросы и Ответы. (Q and A (or FAQ))

После прочтения этого документа, вы должны прочитать и L<perlunifaq> тоже.

=head1 БЛАГОДАРНОСТИ

Спасибо Джохану Вромансу (Johan Vromans) из Squirrel Consultancy. Его замечательная речь про UTF-8  во время
встречи Амстердам Perl Монгерс заинтересовала меня и позволила выяснить,
как использовать кодировки символов в Perl способами, которые не ломаются легко.

Спасибо Джерарду Гуссену (Gerard Goossen) из TTY. Его презентация "UTF-8 в дикой природе" ("UTF-8 in the wild")(Голландский
Perl-воркшоп 2006) вдохновила меня опубликовать мои мысли и написать этот учебник.

Спасибо людям, которые просили о такого рода вещах в нескольких Perl IRC
каналах и постоянно напоминают мне о том, что требуется более простое объяснение.

Спасибо людям, которые рассмотрели этот документ для меня прежде, чем он дошел до общественности.
Это: Бенджамин Смит (Benjamin Smith), Ян-Питер Корнет (Jan-Pieter Cornet), Джохан Вроманс (Johan Vromans),
 Лукас Май (Lukas Mai), Натан Грей (Nathan Gray).

=head1 АВТОР

Юерд Ваалбоер (Juerd Waalboer) <#####@juerd.nl>

=head1 СМОТРИТЕ ЕЩЕ

L<perlunifaq>, L<perlunicode>, L<perluniintro>, L<Encode>

=head1 ПЕРЕВОДЧИКИ
 
=over
 
=item * Николай Мишин C<< <mi@ya.ru> >>
 
=back
