Làm thế nào để các chuỗi perl đại diện trong nội bộ? Mã hóa nào được sử dụng? Làm cách nào để xử lý các mã hóa khác nhau đúng cách?Perl strings internals
Tôi đã sử dụng perl trong một thời gian dài, nhưng nó không bao gồm xử lý chuỗi trong các mã hóa khác nhau và khi gặp phải một vấn đề nhỏ liên quan đến mã hóa tôi thường sử dụng hành động shamanic.
Cho đến thời điểm này, tôi đã nghĩ về chuỗi perl như chuỗi các byte, đã phù hợp khá tốt cho các tác vụ của tôi. Bây giờ tôi cần phải làm một số xử lý của tập tin mã hóa UTF-8 và ở đây bắt đầu gặp rắc rối.
Trước tiên, tôi đọc tập tin vào chuỗi như thế này:
open(my $in, '<', $ARGV[0]) or die "cannot open file $ARGV[0] for reading";
binmode($in, ':utf8');
my $contents;
{
local $/;
$contents = <$in>;
}
close($in);
sau đó chỉ cần in nó:
print $contents;
Và tôi nhận được hai điều: một cảnh báo Wide character in print at <scriptname> line <n>
và rác trong giao diện điều khiển. Vì vậy, tôi có thể kết luận rằng chuỗi perl có khái niệm "ký tự" có thể là "rộng" hay không, nhưng khi in các ký tự "rộng" này được biểu diễn trong bảng điều khiển dưới dạng nhiều byte, không phải là "ký tự" đơn. (Tôi tự hỏi tại sao tất cả kinh nghiệm trước đó của tôi với các tệp nhị phân hoạt động khá như thế nào tôi mong đợi nó hoạt động mà không có bất kỳ vấn đề "nhân vật" nào).
Tại sao sau đó tôi thấy rác trong bảng điều khiển? Nếu perl lưu trữ chuỗi như ký tự trong một số mã hóa đã biết, tôi không nghĩ rằng có một vấn đề lớn để tìm ra bảng điều khiển mã hóa và in văn bản đúng cách. (Tôi sử dụng Windows, BTW).
Nếu perl lưu trữ chuỗi dưới dạng chuỗi ký tự có độ rộng thay đổi (ví dụ: sử dụng cùng một mã UTF-8), tại sao nó được thực hiện theo cách này? Từ chuỗi xử lý trải nghiệm C của tôi là PAIN.
Cập nhật.
Tôi sử dụng hai máy tính để thử nghiệm, một máy chạy Windows 7 x64 với gói ngôn ngữ tiếng Anh được cài đặt, nhưng với cài đặt khu vực của Nga (vì vậy tôi có cp866 là mã OEM và cp1251 là ANSI) với ActivePerl 5.10.1 x64; người khác chạy Windows XP 32 bit bản địa hóa tiếng Nga với Cygwin Perl 5.10.0.
Nhờ liên kết, giờ đây tôi đã hiểu rõ hơn về những gì đang diễn ra và cách thức thực hiện.
Bằng các chuỗi nhiều byte, tôi có nghĩa là mã hóa độ rộng biến đổi. – n0rd
Dù sao tôi không hiểu tại sao tôi phải chuyển đổi một cách rõ ràng: Tôi đã chỉ định mã hóa dữ liệu đầu vào tại sao tôi phải thực hiện một số bước bổ sung? – n0rd
Bạn đã chỉ định mã hóa đầu vào. Bạn làm công cụ của bạn. Sau đó, bạn chỉ định mã hóa đầu ra của mình. Các bài viết tôi gọi là giải thích tốt hơn, tôi nên suy nghĩ. – dylan