2009-12-22 32 views
20

Khi sử dụng trình thông dịch scala (tức là chạy lệnh 'scala' trên dòng lệnh), tôi không thể in chính xác các ký tự unicode. Tất nhiên a-z, A-Z, vv được in chính xác, nhưng ví dụ € hoặc ƒ được in dưới dạng?.In Unicode từ trình thông dịch Scala

print(8364.toChar) 

kết quả? thay vì €. Có lẽ tôi đang làm điều gì sai. Thiết bị đầu cuối của tôi hỗ trợ các ký tự utf-8 và ngay cả khi tôi đưa đầu ra vào một tệp riêng biệt và mở nó trong một trình soạn thảo văn bản,? được hiển thị.

này được tất cả xảy ra trên Mac OS X (Snow Leopard, 10.6.2) với Scala 2.8 (đêm xây dựng) và Java 1.6.0_17)

+0

Trong hệ điều hành nào bạn đang chạy trình thông dịch? Và phiên bản Scala nào? –

+0

Được thêm vào bài đăng gốc của tôi –

Trả lời

16

tôi tìm ra nguyên nhân của vấn đề, và một giải pháp để làm cho nó làm việc như nó phải. Như tôi đã nghi ngờ sau khi đăng câu hỏi của tôi và đọc câu trả lời của Calum và các vấn đề với mã hóa trên Mac với một dự án khác (trong Java), nguyên nhân của sự cố là mã hóa mặc định được Mac OS X. scala thông dịch viên, nó sẽ sử dụng mã hóa mặc định cho nền tảng được chỉ định. Trên Mac OS X, đây là Macroman, trên Windows có lẽ là CP1252. Bạn có thể kiểm tra điều này bằng cách gõ lệnh sau trong thông dịch scala:

scala> System.getProperty("file.encoding"); 
res3: java.lang.String = MacRoman 

Theo sự giúp đỡ kiểm tra scala, nó có thể cung cấp các đặc tính Java sử dụng tùy chọn -D. Tuy nhiên, điều này không làm việc cho tôi. Tôi đã kết thúc thiết lập các biến môi trường

JAVA_OPTS="-Dfile.encoding=UTF-8" 

Sau khi chạy scala, kết quả của lệnh trước đó sẽ cung cấp cho các kết quả sau:

scala> System.getProperty("file.encoding") 
res0: java.lang.String = UTF-8 

Bây giờ, in ký tự đặc biệt hoạt động như mong đợi:

print(0x20AC.toChar)    
€ 

Vì vậy, nó không phải là một lỗi trong Scala, nhưng là một vấn đề với mã hóa mặc định. Theo tôi, nó sẽ tốt hơn nếu theo mặc định UTF-8 được sử dụng trên tất cả các nền tảng. Trong tìm kiếm của tôi cho một câu trả lời nếu điều này được xem xét, tôi đi qua một discussion trên danh sách gửi thư Scala về vấn đề này.Trong tin nhắn đầu tiên, nó được đề xuất sử dụng UTF-8 theo mặc định trên Mac OS X khi file.encoding báo cáo Macroman, vì UTF-8 là bộ mã mặc định trên Mac OS X (giữ tôi tự hỏi tại sao file.encoding theo mặc định được đặt thành Macroman, có thể đây là một thừa kế từ Mac OS trước khi 10 được phát hành?). Tôi không nghĩ rằng đề xuất này sẽ là một phần của Scala 2.8, kể từ Martin Odersky wrote rằng có lẽ tốt nhất là giữ mọi thứ như trong Java (tức là tôn trọng tài sản file.encoding).

+0

Để báo giá Sun: _Đặc tính "file.encoding" không được yêu cầu bởi đặc tả nền tảng J2SE; đó là một chi tiết nội bộ về việc triển khai của Sun và không nên được kiểm tra hoặc sửa đổi bởi mã người dùng. Nó cũng có ý định chỉ đọc; về mặt kỹ thuật, không thể hỗ trợ cài đặt thuộc tính này thành các giá trị tùy ý trên dòng lệnh hoặc vào bất kỳ lúc nào khác trong quá trình thực thi chương trình._ http://bugs.sun.com/view_bug.do?bug_id=4163515 Vì vậy, nó không phải là được hỗ trợ, có thể không hoạt động trên tất cả các JVM và có thể có các tác dụng phụ không mong muốn. – McDowell

+1

Một cách để thực hiện điều này trong khi tránh vấn đề cờ McDowell là bọc System.out PrintStream (vẫn còn hoạt động như một OutputStream thô) với PrintStream sử dụng mã hóa bạn muốn, sau đó sử dụng nó, chẳng hạn như "val myOut = PrintStream mới (System.out, "UTF-8"); myOut.print (0x20AC.toChar) ". Điều này sẽ luôn luôn hoạt động. Tôi sẽ sửa đổi điều này nhưng tôi không nghĩ rằng tôi có nghiệp cho loại điều đó. – Calum

+1

@Calum - thật thú vị khi xem điều đó có hoạt động trên máy Mac hay không; nó không hoạt động tốt trên Windows, nhưng nó có thể là một vấn đề nền tảng cụ thể: http://illegalargumentexception.blogspot.com/2009/04/i18n-unicode-at-windows-command-prompt.html#charsets_javaconsole – McDowell

3

Ok, ít nhất là một phần, nếu không muốn nói là tất cả, vấn đề của bạn đây là 128 không phải là codepoint Unicode cho Euro. 128 (hoặc 0x80 kể từ hex có vẻ là chuẩn) là U+0080 <control>, nghĩa là nó không phải là ký tự có thể in, do đó không có gì đáng ngạc nhiên khi thiết bị đầu cuối của bạn gặp sự cố khi in.

điểm mã của Euro là 0x20AC (hoặc trong thập phân 8364), và điều đó dường như làm việc cho tôi (Tôi đang trên Linux, trên một đêm 2,8):

scala> print(0x20AC.toChar) 
€ 

Một thử nghiệm thật thú vị để in Unicode snowman character:

scala> print(0x2603.toChar) 
☃ 

128 vì dường như là ký tự mở rộng từ một trong các trang mã Windows.

tôi có các nhân vật khác mà bạn đề cập đến việc quá:

scala> 'ƒ'.toInt 
res8: Int = 402 

scala> 402.toChar 
res9: Char = ƒ 
+0

Bạn nói đúng về số sai cho ký hiệu Euroo. Tuy nhiên, nó vẫn không hoạt động đối với tôi: scala> in (0x20AC.toChar) ? Nhưng nếu nó hoạt động trong hàng đêm của bạn, nó có thể là một vấn đề với hệ thống của tôi hoặc có thể nó được sửa trong các phiên bản Scala 2.8 mới hơn. Tôi sẽ cập nhật thêm một điều tra. –

+0

Tôi đã kiểm tra điều này hàng đêm '(2.8.0.r20300-b20091223020158) và' in (0x20AC.toChar) 'in dấu chấm hỏi giống như tất cả các phiên bản 2.8 khác mà tôi đã nói dối. – p3t0r

+0

Tôi đang sử dụng OSX 10.6.2. – p3t0r

0

Đối với Windows trong dòng lệnh (cmd) in:

  1. set JAVA_OPTS="-Dfile.encoding=UTF-8"
  2. chcp 65001

khoản 2 có nghĩa là UTF-8

Nếu bạn không muốn in mỗi lần " chcp 65001 ", bạn có thể thay đổi/thêm giá trị trong Windows Registry như sau:

  1. Run lệnh regedit
  2. tìm kỷ lục [HKEY_CURRENT_USER \ Software \ Microsoft \ Command Processor]
  3. New => String value
  4. Tên = "AutoRun", dữ liệu = "chcp 65001" (không có dấu ngoặc kép)

(thấy https://superuser.com/a/482117/454417)

tôi sử dụng Windows 10 và scala 2.11.8

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