В документации идущей с Perl касамо Unicode: perluniintro, perlunicode везде только Encode. С остальным согласен.

On 01/17/2014 03:43 PM, Denis Sokolovsky wrote:
Дозвольте не погодитись. По-перше я не бачив що б всюди рекомендували Encode замість utf8::encode/decode - вони по різному працюють і не можуть виключно заміщати одна одну. По-друге все залежить від мети. utf8::decode більш строгий до корректності utf8 строки ніж Encode, який пробує створити щось валідне будь-що. Натомість utf8::decode не вміє займатись перекодовуванням з будь-чого в utf8. Ось простий приклад, що демострує строгість utf8::decode:

$ perl -MEncode -MDevel::Peek -e '$x = "фів\321"; print "Original\n"; Dump($x); print "Encode/utf8\n"; Dump(Encode::decode("UTF-8", $x)); utf8::decode($x); Dump($x);'
Original
SV = PV(0x92f7750) at 0x9313f08
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x930f5b8 "\321\204\321\226\320\262\321"\0
  CUR = 7
  LEN = 12
Encode/utf8
SV = PV(0x92f7d60) at 0x93935d0
  REFCNT = 1
  FLAGS = (TEMP,POK,pPOK,UTF8)
PV = 0x939ae78 "\321\204\321\226\320\262\357\277\275"\0 [UTF8 "\x{444}\x{456}\x{432}\x{fffd}"]
  CUR = 9
  LEN = 12
SV = PV(0x92f7750) at 0x9313f08
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x930f5b8 "\321\204\321\226\320\262\321"\0
  CUR = 7
  LEN = 12

Відповідно функція is_utf8 для результату Encode видає true, а після utf8::decode строка так і не стала utf8. Я погоджуюсь що для більшості веб задач варто все ж таки використовувати Encode (особливо коли мова стосується данних від користувача) тому що вона майже наглухо fail-proof, але то не є панацея.



2014/1/16 vti <[email protected] <mailto:[email protected]>>

    Не надо путать utf8::* с Encode::*. Везде рекомендуют использовать
    Encode, а не вручную проставлять utf8-флаги. Кроме того используя
    'UTF-8' в Encode, вместо 'utf8', utf-символы кое-как, но
    валидируются.


    On 01/16/2014 03:47 PM, Denis Sokolovsky wrote:

    Вставлю і я свої 5 копійок: utf8::encode/decode нічого не
    перекодовують, а просто помічають скаляр як такий що містить не
    байти, а символи. Це дозволяє perl відповідно працювати з такими
    скалярами. Може такий приклад трохи прояснить ситуацію:

    $ perl -MDevel::Peek -e '$x = "фів"; Dump($x); utf8::decode($x);
    Dump($x)'

    SV = PV(0x1ceed80) at 0x1d0d4b8

      REFCNT = 1

      FLAGS = (POK,pPOK)

      PV = 0x1cfc5e0 "\321\204\321\226\320\262"\0

      CUR = 6

      LEN = 16

    SV = PV(0x1ceed80) at 0x1d0d4b8

      REFCNT = 1

      FLAGS = (POK,pPOK,UTF8)

      PV = 0x1cfc5e0 "\321\204\321\226\320\262"\0 [UTF8
    "\x{444}\x{456}\x{432}"]

      CUR = 6

      LEN = 16


    Відповідно ці функції відмінно лягають в процес описаний
    Турським: на вході для отримання з байтів символів викоикаємо
    decode, на виході для того щоб віддавати байти: encode. Додаткові
    опції, назразок того самого :utf8 для open просто автоматизують
    данну операцію.

-- Denis Sokolovsky

    On Jan 16, 2014 3:24 PM, "vti" <[email protected]
    <mailto:[email protected]>> wrote:

        On 01/16/2014 03:09 PM, [email protected]
        <mailto:[email protected]> wrote:

                Во-первых, лучше использовать use utf8; вместо use
                encoding 'utf8';, т.к.
                согласно http://perldoc.perl.org/encoding.html
                данная прагма в 5.18+ является deprecated.

            Спасибо

                use open qw/:std :utf8/;
                use utf8;
                use CGI qw/:standard -utf8/;

            Вот как раз если добавлять :std, то ломаются данные из
            простой формы
            на данный момент рабочий вариант вот такой:

            use open qw/:utf8/;
            use utf8;
            use CGI qw/:standard -utf8/;

            Но  у него есть мелкий недостаток, он не правильно
            выводит русское название
            файла при glob("*").
            Можно конечно использовать костыль, предложенный vti, в виде
            Encode::decode('UTF-8', $_);
            Тем более, что русских файлов в принципе не желательно
            держать.

            Для тех кто хочет потестить (посмотреть):
            Пожалуйста http://www.ahost.com.ua/utf8/index.cgi
            FTP: admin_utf8 / utf8
            http://77.120.116.161/myadmin admin_utf8 / utf8


        Перекодировка -- это не костыль. Процитирую свои изменения в
        тот файл:

        Рекомендации по UTF-8:
        1. print должен быть в UTF-8: binmode(STDOUT, ":utf8");
        2. glob возвращает файл в байтах, необходимо преобразовать в
        UTF-8: my
        $file = Encode::decode('UTF-8', $_);
        3. при открытии файла необходимо сообщить, что мы хотим
        автоматически
        UTF-8: open(FILE, '<:encoding(UTF-8)', "$file");
        4. вместо use encoding 'utf-8' использовать use utf8; и
        только тогда,
        когда в исходном тексте программы есть UTF-8 символы (в
        данном случае есть)
        5. с базой вижу есть вариант правильный (set names +
        mysql_enable_utf8),
        надеюсь, что и в схеме стоит кодировка UTF-8 (иначе будет
        каша потом)

        Сократить этот список можно используя utf8::all.
        _______________________________________________
        Kiev-pm mailing list
        [email protected] <mailto:[email protected]>
        http://mail.pm.org/mailman/listinfo/kiev-pm



    _______________________________________________
    Kiev-pm mailing list
    [email protected]  <mailto:[email protected]>
    http://mail.pm.org/mailman/listinfo/kiev-pm


    _______________________________________________
    Kiev-pm mailing list
    [email protected] <mailto:[email protected]>
    http://mail.pm.org/mailman/listinfo/kiev-pm




--
Denis Sokolovsky


_______________________________________________
Kiev-pm mailing list
[email protected]
http://mail.pm.org/mailman/listinfo/kiev-pm

_______________________________________________
Kiev-pm mailing list
[email protected]
http://mail.pm.org/mailman/listinfo/kiev-pm

Ответить