2009-10-23 53 views
7

Tôi đã biết làm thế nào để chuyển đổi các nội dung không utf8 mã hóa của một dòng tập tin bằng dòng sang UTF-8 mã hóa, sử dụng một cái gì đó giống như đoạn mã sau:Làm cách nào để chuyển đổi tệp đầu vào thành mã hóa UTF-8 trong Perl?

# outfile.txt is in GB-2312 encode  
open my $filter,"<",'c:/outfile.txt'; 

while(<$filter>){ 
#convert each line of outfile.txt to UTF-8 encoding 
    $_ = Encode::decode("gb2312", $_); 
...} 

Nhưng tôi nghĩ rằng Perl có thể trực tiếp mã hóa toàn bộ tập tin đầu vào sang định dạng UTF-8, một cái gì đó vì vậy tôi đã cố gắng như

#outfile.txt is in GB-2312 encode 
open my $filter,"<:utf8",'c:/outfile.txt'; 

(Perl nói điều gì đó như "utf8 "\ xD4" không bản đồ để Unicode")

open my $filter,"<",'c:/outfile.txt'; 
$filter = Encode::decode("gb2312", $filter); 

(Perl nói "readline() trên filehandle chưa mở!)

Họ không làm việc. Nhưng có cách nào để trực tiếp chuyển đổi tập tin đầu vào sang mã hóa UTF-8 không?

Cập nhật:

Hình như mọi thứ không đơn giản như tôi nghĩ. Bây giờ tôi có thể chuyển đổi tập tin đầu vào thành mã UTF-8 theo cách đường vòng. Trước tiên, tôi mở tệp đầu vào và sau đó mã hóa nội dung của nó thành UTF-8 rồi xuất ra tệp mới và sau đó mở tệp mới để xử lý tiếp. Đây là mã:

open my $filter,'<:encoding(gb2312)','c:/outfile.txt'; 
open my $filter_new, '+>:utf8', 'c:/outfile_new.txt'; 
print $filter_new $_ while <$filter>; 
while (<$filter_new>){ 
... 
} 

Nhưng đây là quá nhiều công việc và thậm chí còn phiền phức hơn việc mã hóa nội dung của dòng lọc $ theo dòng.

+3

Bất cứ khi nào bạn đề cập đến thông báo cảnh báo trong câu hỏi, hãy bao gồm thông báo cảnh báo trong câu hỏi. :) –

+0

@brian, cảm ơn đề xuất. – Mike

+1

Tốt nhất là sử dụng thông điệp cảnh báo chính xác :) Vì vậy, với cảnh báo đó, bạn cần phải kiểm tra kết quả mở của bạn (mà bạn nên luôn luôn làm anyway). –

Trả lời

5

Tôi nghĩ rằng tôi đã hiểu nhầm câu hỏi của bạn. Tôi nghĩ rằng những gì bạn muốn làm là đọc một tập tin trong một mã hóa không phải UTF-8, sau đó chơi với các dữ liệu như UTF-8 trong chương trình của bạn. Đó là một cái gì đó dễ dàng hơn nhiều. Sau khi bạn đọc dữ liệu với mã hóa đúng, Perl đại diện cho nó bên trong là UTF-8. Vì vậy, chỉ cần làm những gì bạn phải làm.

Khi bạn viết lại, hãy sử dụng bất kỳ mã hóa nào bạn muốn lưu. Tuy nhiên, bạn không cần phải đặt nó trở lại trong một tập tin để sử dụng nó.


câu trả lời cũ

Các Perl I/O lớp chỉ đọc dữ liệu giả sử nó đã được mã hóa đúng cách. Nó sẽ không chuyển đổi mã hóa cho bạn. Bằng cách nói mở để sử dụng utf8, bạn đang nói với nó rằng nó đã là utf8.

Bạn phải sử dụng mô-đun Encode giống như bạn đã hiển thị (trừ khi bạn muốn viết lớp I/O của riêng mình). Bạn có thể chuyển đổi byte sang UTF-8, hoặc nếu bạn biết mã hóa, bạn có thể chuyển đổi từ một mã hóa sang mã hóa khác. Vì có vẻ như bạn đã biết mã hóa, bạn có thể muốn hàm from_to().

Nếu bạn mới bắt đầu với Perl và Unicode, hãy xem qua Juerd's Perl Unicode Advice trước khi bạn làm bất cứ điều gì.

+0

@brian, cảm ơn sự hướng dẫn. Tôi nghĩ rằng nên có một số cách đơn giản để trực tiếp chuyển đổi các tập tin đầu vào để mã hóa UTF-8 trong khi mở nó. Nhưng bây giờ có vẻ như mọi thứ không đơn giản như vậy. Tôi nghĩ tôi có thể mở tập tin đầu vào trước và sau đó mã hóa nội dung thành UTF-8 rồi xuất ra một tệp khác trong mã hóa UTF-8 và sau đó mở một tệp khác. Mã trông giống như: mở bộ lọc $ của tôi, '<: encoding (gb2312)', 'c: /outfile.txt'; mở $ filter_new của tôi, '+>: utf8', 'c: /f2.txt'; in $ filter_new $ _ trong khi <$filter>; trong khi (<$filter_new>) {...} Nhưng đây là quá nhiều việc. trong khi (<$fh_out>) { – Mike

+0

Ý tưởng của bạn về quá nhiều công việc bị lệch. Hãy thử làm điều đó bằng tay và sau đó quay trở lại và cho chúng tôi biết Perl dễ dàng như thế nào cho bạn. Trẻ em ngày hôm nay không biết làm thế nào tốt họ có nó. :) –

+0

Bản năng của Mike là chính xác; bạn có thể ngăn xếp các lớp để trực tiếp thực hiện chuyển đổi mà anh ta muốn :) – ysth

4

Lớp mã hóa: sẽ trả về UTF-8, thích hợp cho việc sử dụng của perl. Tức là, perl sẽ nhận ra từng ký tự như một ký tự, ngay cả khi chúng là nhiều byte. Tùy thuộc vào những gì bạn sẽ làm tiếp theo với dữ liệu, điều này có thể là đủ.Tuy nhiên, nếu bạn đang làm điều gì đó với dữ liệu mà perl sẽ cố gắng hạ cấp nó từ utf8, bạn cần phải nói với perl không (ví dụ, làm một binmode (STDOUT, ": utf8") để nói với perl rằng đầu ra để stdout nên được utf8), hoặc bạn cần phải có perl đối xử với utf8 của bạn như là dữ liệu nhị phân (giải thích từng byte riêng biệt, và không biết gì về các ký tự utf8.)

Để làm điều đó, tất cả những gì bạn cần là áp dụng lớp bổ sung để mở của bạn:

open my $foo, "<:encoding(gb2312):bytes", ...; 

Lưu ý rằng đầu ra sau đây sẽ giống nhau:

perl -we'open my $foo, "<:encoding(gb2312):bytes", "foo"; $bar = <$foo>; print $bar' 
perl -CO -we'open my $foo, "<:encoding(gb2312)", "foo"; $bar = <$foo>; print $bar' 

nhưng trong một trường hợp, perl biết rằng đọc dữ liệu là utf8 (và độ dài ($ bar) sẽ báo cáo số lượng ký tự utf8) và phải được thông báo rõ ràng (by -CO) rằng STDOUT sẽ chấp nhận utf8 , và trong trường hợp khác, perl không đưa ra giả định nào về dữ liệu (và do đó chiều dài ($ bar) sẽ báo cáo số byte) và chỉ in ra như vậy.

Các vấn đề liên quan