2010-11-10 40 views

Trả lời

31

Những gì bạn nghe đã lỗi thời và áp dụng (chỉ một phần) với Ruby 1.8 hoặc trước đó. Phiên bản ổn định mới nhất của Ruby (1.9), hỗ trợ không ít hơn mã hóa ký tự khác nhau (được tính trên hệ thống của tôi ngay bây giờ). Điều này bao gồm khá nhiều định dạng chuyển đổi Unicode đã biết, bao gồm UTF-8.

Phiên bản ổn định trước của Ruby (1.8) có hỗ trợ một phần cho UTF-8.

Nếu bạn sử dụng Rails, nó sẽ chăm sóc mã hóa UTF-8 mặc định cho bạn. Nếu tất cả những gì bạn cần là nhận thức mã hóa UTF-8, Rails sẽ làm việc cho bạn cho dù bạn chạy Ruby 1.9 hay Ruby 1.8. Nếu bạn có yêu cầu mã hóa ký tự rất cụ thể, bạn nên hướng đến Ruby 1.9.

Nếu bạn thực sự quan tâm, dưới đây là series of articles mô tả các vấn đề mã hóa trong Ruby 1.8 và cách chúng hoạt động, và cuối cùng được giải quyết trong Ruby 1.9. Rails vẫn bao gồm các giải pháp cho nhiều lỗ hổng phổ biến trong Ruby 1.8.

+0

cho bất kỳ ai thích bản thân mình tìm kiếm lối tắt đến $ KCODE tương đương với công tắc mã hóa mặc định có lập trình, những gì bạn muốn là: Encoding.default_internal = 'utf-8' # Encoding.list.map (&: name) – Travis

+0

Liên kết đã chết. :( – user2357112

14

Điều đó không đúng. Điều đúng là Ruby không hỗ trợ chỉ Unicode, nó cũng hỗ trợ toàn bộ các mã hóa khác.

Điều này trái ngược với các hệ thống như Java, .NET hoặc Python, tuân theo mô hình "Một mã hóa để quy tắc tất cả". Ruby có một trong những nhà thiết kế hệ thống m17n của Ruby gọi một mô hình "CSI" (Code Set Indepedent), có nghĩa là thay vì tất cả các chuỗi chỉ có một và cùng một mã hóa, mỗi chuỗi được gắn với mã hóa riêng của nó.

Điều này có một số lợi thế đáng kể cả về tính dễ sử dụng và hiệu suất, bởi vì nó có nghĩa là nếu mã hóa đầu vào và đầu ra của bạn giống nhau, bạn không bao giờ cần phải chuyển mã, trong khi với mô hình Mã hóa thực, bạn cần chuyển mã hai lần trong trường hợp xấu nhất (và trường hợp xấu nhất không may xảy ra khá thường xuyên, vì hầu hết các môi trường này đã chọn mã hóa nội bộ mà không ai thực sự sử dụng), từ mã hóa đầu vào vào mã hóa nội bộ và sau đó đến mã hóa đầu ra. Trong Ruby, bạn cần chuyển mã nhiều nhất một lần.

Vấn đề cơ bản với mô hình OTE là bất kỳ mã hóa nào bạn chọn là Mã hóa thực, nó sẽ là lựa chọn hoàn toàn tùy ý, vì đơn giản không phải là mã hóa duy nhất mà mọi người sử dụng.

Trong Java, ví dụ, họ đã chọn UCS-2 làm Mã hóa thực. Sau đó, một vài năm sau, hóa ra UCS-2 thực sự không đủ để mã hóa tất cả các ký tự, vì vậy họ phải thực hiện một sự thay đổi không tương thích ngược với Java, để chuyển sang UTF-16 thành Mã hóa thực. Ngoại trừ thời gian đó, một phần đáng kể của thế giới đã chuyển từ UTF-16 sang UTF-8. Nếu Java đã được phát minh ra một vài năm trước đó, họ có thể đã chọn ASCII là Mã hóa thực sự. Nếu nó đã được phát minh ở một quốc gia khác, nó có thể là Shift-JIS. Nếu nó đã được phát minh bởi một công ty khác, nó có thể là EBCDIC. Đó là thực sự là hoàn toàn tùy ý và một lựa chọn quan trọng như vậy không nên là.

+0

Rất thú vị, cảm ơn rất nhiều –

+14

Unicode không phải là mã hóa – tchrist

+3

@tchrist: Đó là mã hóa theo nghĩa là nó gán một số * duy nhất * cho mỗi ký tự (nghĩa là định nghĩa từ điển của từ điển) "). Nó không phải là một mã hóa theo nghĩa là nó không gán một mẫu * bit duy nhất * cho mỗi ký tự (trong Unicode lingo, đó là công việc của định dạng chuyển đổi). Thật không may, tôi chưa bao giờ có thể xuất hiện một tên tốt cho Unicode là gì, khác với "mã hóa" –

0

Trong this answer cho một câu hỏi khác, một người cho biết họ gặp sự cố với Iconv khi xử lý dữ liệu unicode trong Ruby 1.9, nhưng tôi không thể xác minh tính chính xác của nó.

15

Thêm dòng sau vào đầu tệp của tôi đã giải quyết được.

# encoding: utf-8 
+1

trên đầu trang của những gì ??? –

+0

Trên đầu trang của tệp mã nguồn. – Kannaiyan

+0

Yup, ngay sau dòng [http://en.wikipedia.org/wiki/Shebang_(Unix)]. –

5

Đây là câu hỏi khá cũ. Phiên bản ổn định hiện tại của Ruby là 2.0.1. Có, nó xử lý hầu hết các của những gì bạn có thể ném trong Unicode vào nó, nhưng xin lưu ý rằng nó phá vỡ khá dễ dàng.

Hãy xem mẫu và kết quả mã này (lấy cảm hứng từ this):

["noël","","baffle"].each do |str| 
    puts "Result for '#{str}'" 
    puts " Size: #{str.size}" 
    puts " Reverse: [#{str.reverse}]" 
    puts " Uppercase: [#{str.upcase}]" 
end 

Result for 'noël' 
    Size: 5 << bad size 
    Reverse: [l̈eon] <= accent is shifted 
    Uppercase: [NOËL] 
Result for '' 
    Size: 2 
    Reverse: [] 
    Uppercase: [] 
Result for 'baffle' 
    Size: 4 
    Reverse: [efflab] <= doesn't really make sense 
    Uppercase: [BAfflE] <= should be "ELFFAB" 

Vấn đề là: Ruby hiện đại xử lý các vấn đề cơ bản - tính năng chuỗi tiên tiến hơn không nên được tính vào.

+0

Tôi không nhận được bình luận của bạn. Tại sao 'e ffl ab' không phải là sự đảo ngược của' ba ffl e' có ý nghĩa? Hoặc tại sao chữ hoa của 'ba ffl e' là' ELFFAB'? – eis

+0

đảo ngược của 'baffle' phải là' elffab', không phải 'efflab' :-) – kralyk

+3

@kralyk @GregPK Có vẻ như' ba ffl e' được xử lý chính xác, vì ffl là một ký tự đơn. Nó thực sự có ý nghĩa. :) – ray

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