2012-01-19 92 views
22

Khi tôi sử dụng biểu tượng để chuyển đổi từ UTF16 sang UTF8 thì tất cả đều tốt nhưng ngược lại nó không hoạt động. Tôi có các tệp này:Chuyển đổi UTF8 sang UTF16 bằng cách sử dụng biểu tượng

a-16.strings: Little-endian UTF-16 Unicode c program text 
a-8.strings:  UTF-8 Unicode c program text, with very long lines 

Văn bản trông OK trong trình chỉnh sửa. Khi tôi chạy này:

iconv -f UTF-8 -t UTF-16LE a-8.strings > b-16.strings 

Sau đó, tôi nhận được kết quả này:

b-16.strings: data 
a-16.strings: Little-endian UTF-16 Unicode c program text 
a-8.strings:  UTF-8 Unicode c program text, with very long lines 

Tiện ích file không hiển thị định dạng tập tin dự kiến ​​và văn bản không nhìn tốt trong trình soạn thảo một trong hai. Nó có thể được rằng iconv không tạo ra BOM phù hợp? Tôi chạy nó trên dòng lệnh MAC.

Tại sao không phải là b-16 ở định dạng UTF-16LE phù hợp? Có cách nào khác để chuyển đổi utf8 thành utf16?

Công cụ xây dựng khác dưới đây.

$ iconv -f UTF-8 -t UTF-16LE a-8.strings > b-16le-BAD-fromUTF8.strings 
$ iconv -f UTF-8 -t UTF-16 a-8.strings > b-16be.strings 
$ iconv -f UTF-16 -t UTF-16LE b-16be.strings > b-16le-BAD-fromUTF16BE.strings 

$ file *s 
a-16.strings:     Little-endian UTF-16 Unicode c program text, with very long lines 
a-8.strings:     UTF-8 Unicode c program text, with very long lines 
b-16be.strings:     Big-endian UTF-16 Unicode c program text, with very long lines 
b-16le-BAD-fromUTF16BE.strings: data 
b-16le-BAD-fromUTF8.strings: data 


$ od -c a-16.strings | head 
0000000 377 376 /\0 * \0  \0 \f 001 E \0 S \0 K \0 

$ od -c a-8.strings | head 
0000000 / * * *  Č ** E S K Y  ( J V O 

$ od -c b-16be.strings | head 
0000000 376 377 \0 /\0 * \0 * \0 * \0  001 \f \0 E 

$ od -c b-16le-BAD-fromUTF16BE.strings | head         
0000000 /\0 * \0 * \0 * \0  \0 \f 001 E \0 S \0 

$ od -c b-16le-BAD-fromUTF8.strings | head 
0000000 /\0 * \0 * \0 * \0  \0 \f 001 E \0 S \0 

Rõ ràng BOM bị thiếu bất cứ khi nào tôi chạy chuyển đổi sang UTF-16LE. Bất kỳ trợ giúp nào về điều này?

+0

nếu bạn sử dụng 'iconv -f UTF-8 -t UTF-16LE a-8.strings -o b-16.strings' thay thế? Tôi nghi ngờ nó sẽ sửa chữa nó, nhưng nó có giá trị một shot. – cha0site

+0

phiên bản biểu tượng của tôi không hỗ trợ tham số -o (MacOS). Như bạn đã nói, nó có thể sẽ không giúp được gì. Cảm ơn bạn đã thử. –

+0

Đầu ra của bạn hiển thị 'iconv -f UTF-8 -t UTF-16 a-8.string' (chạy trên hệ thống nhỏ) tạo ra UTF-16 lớn với BOM. Bạn có thể xác nhận điều đó không? Lệnh Mac icon '' có hoạt động khác với lệnh trên Linux không? 'echo hello | iconv -f ascii -t UTF-16 | od -x' –

Trả lời

31

UTF-16LE yêu cầu iconv để tạo ít người dùng UTF-16 mà không cần một BOM (Dấu đơn hàng). Rõ ràng nó giả định rằng kể từ khi bạn chỉ định LE, BOM là không cần thiết.

UTF-16 yêu cầu tạo văn bản UTF-16 (theo thứ tự byte của máy cục bộ) với một BOM.

Nếu bạn đang sử dụng máy tính nhỏ gọn, tôi không thấy cách nào để nói iconv để tạo UTF-16 lớn với BOM, nhưng tôi có thể chỉ thiếu một thứ gì đó.

Tôi thấy rằng lệnh file không nhận dạng được văn bản UTF-16 mà không có BOM và trình chỉnh sửa của bạn có thể không. Nhưng nếu bạn chạy iconv -f UTF-16LE -t UTF_8 b-16 strings, bạn sẽ nhận được phiên bản UTF-8 hợp lệ của tệp gốc.

Thử chạy od -c trên các tệp để xem nội dung thực tế của chúng.

UPDATE:

Dường như bạn đang ở trên một máy lớn-endian (x86 rất ít về cuối nhỏ), và bạn đang cố gắng để tạo ra một tập tin ít về cuối nhỏ UTF-16 với BOM . Đúng không? Theo như tôi có thể nói, iconv sẽ không thực hiện điều đó trực tiếp. Nhưng điều này nên làm việc:

(printf "\xff\xfe" ; iconv -f utf-8 -t utf-16le UTF-8-FILE) > UTF-16-FILE 

Các hành vi của sức printf phụ thuộc vào cài đặt ngôn ngữ của bạn; Tôi có LANG=en_US.UTF-8.

(Mọi người có thể đề xuất giải pháp thanh lịch hơn không?)

Một workaround, nếu bạn biết endianness của sản lượng sản xuất bởi -t utf-16:

iconv -f utf-8 -t utf-16 UTF-8-FILE | dd conv=swab 2>/dev/null 
+0

Cảm ơn Keith đã giúp đỡ. Tôi đã chỉnh sửa câu hỏi ban đầu của mình với nhiều kết quả hơn dựa trên sự trợ giúp của bạn. Bạn có biết cách sửa nó không? Điều gì xảy ra nếu tôi chỉ dính BOM vào đó? –

+0

Xem câu trả lời được cập nhật. –

+0

Tôi cũng sử dụng máy tính chạy Intel nhưng chạy MacOS. Không bao giờ-ít hơn việc bổ sung bằng tay của BOM như bạn đã đề xuất các công trình tuyệt vời. Cảm ơn rất nhiều! –

0

Điều này có thể không phải là một giải pháp thanh lịch nhưng tôi tìm thấy một cách thủ công để đảm bảo chuyển đổi chính xác cho vấn đề của tôi mà Tôi tin là tương tự như chủ đề của chủ đề này.

Vấn đề: tôi nhận được một datafile văn bản từ một người sử dụng và tôi sẽ xử lý nó trên Linux (đặc biệt là Ubuntu) sử dụng shell script (tokenization, tách, vv). Hãy gọi tập tin myfile.txt. Dấu hiệu đầu tiên mà tôi nhận thấy có điều gì đó không ổn là tokenization không hoạt động. Vì vậy, tôi không ngạc nhiên khi tôi chạy lệnh file trên myfile.txt và nhận được những điều sau

$ file myfile.txt 

myfile.txt: Little-endian UTF-16 Unicode text, with very long lines, with CRLF line terminators 

Nếu tập tin là phù hợp, đây là những gì cần phải có được cuộc nói chuyện:

$ file myfile.txt 

myfile.txt: ASCII text, with very long lines 

Giải pháp: Để làm cho tệp dữ liệu tuân thủ, dưới đây là 3 bước thủ công mà tôi tìm thấy hoạt động sau một số lần thử và lỗi với các bước khác.

  1. Chuyển đổi đầu tiên sang Big Endian bằng cùng một mã hóa qua vi (hoặc vim). vi myfile.txt. Trong vi làm :set fileencoding=UTF-16BE sau đó ghi ra tệp. Bạn có thể phải ép buộc nó với :!wq.

  2. vi myfile.txt (giờ sẽ có trong utf-16BE). Trong vi làm :set fileencoding=ASCII sau đó ghi ra tệp. Một lần nữa, bạn có thể buộc viết với !wq.

  3. Chạy dos2unix trình chuyển đổi: d2u myfile.txt. Nếu bây giờ bạn chạy file myfile.txt bây giờ bạn sẽ thấy một đầu ra hoặc một cái gì đó quen thuộc hơn và đảm bảo như:

    myfile.txt: ASCII text, with very long lines 
    

Vậy là xong. Đó là những gì làm việc cho tôi, và sau đó tôi có thể chạy kịch bản shell bash xử lý của tôi là myfile.txt. Tôi thấy rằng tôi không thể bỏ qua Bước 2. Đó là, trong trường hợp này tôi không thể bỏ qua trực tiếp đến Bước 3. Hy vọng rằng bạn có thể tìm thấy thông tin này hữu ích; hy vọng ai đó có thể tự động hóa nó có lẽ thông qua sed hoặc tương tự. Chúc mừng.

3

Lần đầu tiên tôi chuyển đổi thành UTF-16, sẽ thêm một dấu thứ tự byte, nếu cần as Keith Thompson mentions. Sau đó, kể từ UTF-16 không xác định độ dài, chúng tôi phải sử dụng file để xác định xem đó là UTF-16BE hoặc UTF-16LE. Cuối cùng, chúng tôi có thể chuyển đổi thành UTF-16LE.

iconv -f utf-8 -t utf-16 UTF-8-FILE > UTF-16-UNKNOWN-ENDIANNESS-FILE 
FILE_ENCODING="$(file --brief --mime-encoding UTF-16-UNKNOWN-ENDIANNESS-FILE)" 
iconv -f "$FILE_ENCODING" -t UTF-16LE UTF-16-UNKNOWN-ENDIANNESS-FILE > UTF-16-FILE 
Các vấn đề liên quan