Питання Як я можу вгадати кодування рядка в Perl?


У мене є рядок Unicode і не знаю, що це кодування. Коли цей рядок читається програмою Perl, чи існує стандартне кодування, яке використовуватиме Perl? Якщо так, то як я можу з'ясувати, що це таке?

Я намагаюсь позбутися символів не ASCII від введення. Я знайшов це на якомусь форумі, який це зробить

my $line = encode('ascii', normalize('KD', $myutf), sub {$_[0] = ''});

Як це працює вище, коли не вказано кодування вводу? Чи має бути вказано так?

my $line = encode('ascii', normalize('KD', decode($myutf, 'input-encoding'), sub {$_[0] = ''});

22
2017-12-28 17:52


походження


Виправляю мене, якщо я помиляюся, але я думав, що вся точка Unicode полягає в тому, що вона не має "кодування" - все там. - Paul Tomblin
У вас немає рядка Unicode. У вас є файл з повним байтів, який представляє рядок Unicode в деякій кодуванні. Якщо ви не знаєте кодування файлу, перевірте маркер порядку байта в початку файлу. Якщо немає BOM, вам не повезе. - Jonathan Feinberg
Схоже, ви задаєте щонайменше два окремі питання (перший та другий абзаци). - Amnon
@ Паул: Unicode визначає набір символів. Кодування цього набору символів відображає його на диску. Наприклад, UTF-8 є кодуванням. - brian d foy


Відповіді:


Щоб з'ясувати, в якому кодуванні використовується щось невідоме, потрібно просто спробувати і подивитися. Модулі Кодування :: Визначення і Кодування :: вгадай автоматизувати це. (Якщо у вас виникли проблеми з кодуванням :: Detect, спробуйте його вилку Кодування :: детектив замість цього.)

use Encode::Detect::Detector;
my $unknown = "\x{54}\x{68}\x{69}\x{73}\x{20}\x{79}\x{65}\x{61}\x{72}\x{20}".
              "\x{49}\x{20}\x{77}\x{65}\x{6e}\x{74}\x{20}\x{74}\x{6f}\x{20}".
              "\x{b1}\x{b1}\x{be}\x{a9}\x{20}\x{50}\x{65}\x{72}\x{6c}\x{20}".
              "\x{77}\x{6f}\x{72}\x{6b}\x{73}\x{68}\x{6f}\x{70}\x{2e}";
my $encoding_name = Encode::Detect::Detector::detect($unknown);
print $encoding_name; # gb18030

use Encode;
my $string = decode($encoding_name, $unknown);

я знайшов encode 'ascii' це хитке рішення для позбавлення символів, не пов'язаних з ASCII. Все буде замінено знаками питань; це занадто втрачено, щоб бути корисним.

# Bad example; don't do this.
use utf8;
use Encode;
my $string = 'This year I went to 北京 Perl workshop.';
print encode('ascii', $string); # This year I went to ?? Perl workshop.

Якщо ви хочете отримати читаний ASCII текст, я рекомендую Текст :: Unidecode замість цього. Це теж кодировка втрат, але не така страшна, як простота encode вище.

use utf8;
use Text::Unidecode;
my $string = 'This year I went to 北京 Perl workshop.';
print unidecode($string); # This year I went to Bei Jing  Perl workshop.

Проте уникайте кодувань з втратами, якщо ви можете допомогти. Якщо ви хочете змінити операцію пізніше, виберіть один з PERLQQ або XMLCREF.

use utf8;
use Encode qw(encode PERLQQ XMLCREF);
my $string = 'This year I went to 北京 Perl workshop.';
print encode('ascii', $string, PERLQQ);  # This year I went to \x{5317}\x{4eac} Perl workshop.
print encode('ascii', $string, XMLCREF); # This year I went to 北京 Perl workshop.

29
2017-12-29 12:43



Вхід, який я отримую, завжди використовує латинський набір символів. Функція нормалізації, яку я використовую, перетворить "Café" в "Cafe". Однак це не працює у всіх випадках. З огляду на це, ви все ще вважаєте за краще використовувати метод PERLQQ або XMLCREF? - Maulin
Неважливо, що я віддаю перевагу - це ваш код і відповідальність, і тільки ви знаєте всі обставини. Якщо ви дійсно задоволені Café → Cafe, то замініть свою користувацьку функцію Text::Unidecode. Це працює у всіх випадках. - daxim
Дякую. Я думаю, що я спробую це. - Maulin


The Кодувати модуль має такий спосіб, як ви можете спробувати зробити це. ви decode сирі октети з тим, що ви думаєте, кодування. Якщо октети не відображають коректне кодування, він вибухне, і ви потраплятимете на нього за допомогою eval. В іншому випадку ви отримаєте правильно закодовану рядок. Наприклад:

 use Encode;

 my $a_with_ring =
   eval { decode( 'UTF-8', "\x6b\xc5", Encode::FB_CROAK ) }
     or die "Could not decode string: $@";

У цьому є недолік того, що однакова послідовність октетів може бути дійсною в декількох кодуваннях

Я маю більше сказати про це в майбутньому Ефективне програмування Perl, 2-е видання, в якому є цілий розділ щодо роботи з Unicode. Я думаю, що мій видавник злякався б, якщо б я опублікував все це. :)

Ви також можете побачити Juerd's Unicode Advice, а також деяких документів Unicode, що постачаються з Perl.


3
2017-12-29 08:34





Ви також можете використовувати наступний код, щоб шифрувати та дешифрувати код

sub ENCRYPT_DECRYPT() {
    my $Str_Message=$_[0];
    my  $Len_Str_Message=length($Str_Message);

    my  $Str_Encrypted_Message="";
    for (my $Position = 0;$Position<$Len_Str_Message;$Position++){
        my  $Key_To_Use = (($Len_Str_Message+$Position)+1);
            $Key_To_Use =(255+$Key_To_Use) % 255;
        my  $Byte_To_Be_Encrypted = substr($Str_Message, $Position, 1);
        my  $Ascii_Num_Byte_To_Encrypt = ord($Byte_To_Be_Encrypted);
        my  $Xored_Byte = $Ascii_Num_Byte_To_Encrypt ^ $Key_To_Use;
            my  $Encrypted_Byte = chr($Xored_Byte);
        $Str_Encrypted_Message .= $Encrypted_Byte;

    }
    return $Str_Encrypted_Message;
}

 my $var=&ENCRYPT_DECRYPT("hai");
 print &ENCRYPT_DECRYPT($var);

-4
2018-03-02 10:59



Питання було про кодування тексту, а не про шифрування. - Flimm