2012-04-03 29 views
8

Vì vậy, tôi gặp một số vấn đề với mã hóa ký tự. Khi tôi đặt hai nhân vật sau đây vào một UTF32 mã hóa tập tin văn bản:Sự cố UTF32 và C#

và sau đó chạy đoạn mã này vào chúng:

System.IO.StreamReader streamReader = 
    new System.IO.StreamReader("input", System.Text.Encoding.UTF32, false); 
System.IO.StreamWriter streamWriter = 
    new System.IO.StreamWriter("output", false, System.Text.Encoding.UTF32); 

streamWriter.Write(streamReader.ReadToEnd()); 

streamWriter.Close(); 
streamReader.Close(); 

tôi nhận được:

鸕 
鸕 

(cùng nhân vật hai lần, tức là tệp đầu vào! = đầu ra)

Một vài điều có thể hữu ích: Hex cho ký tự đầu tiên:

15 9E 02 00

Và cho phần thứ hai:

15 9E 00 00

Tôi đang sử dụng gedit để tạo ra tập tin văn bản, mono cho C# và tôi đang sử dụng Ubuntu.

Nó cũng không quan trọng nếu tôi chỉ định mã hóa cho tệp đầu vào hoặc đầu ra, nó chỉ không thích nó nếu nó trong mã hóa UTF32. Nó hoạt động nếu tập tin đầu vào được mã hóa UTF-8.

Các tập tin đầu vào là như sau:

FF FE 00 00 15 9E 02 00 0A 00 00 00 15 9E 00 00 0A 00 00 00

Có một lỗi, hoặc là nó chỉ cho tôi?

Cảm ơn!

+0

Encoding của tập tin đầu ra? –

+0

In kết quả của 'streamReader.ReadToEnd()'. – leppie

+0

@ L.B - Thay đổi nó không giúp được – AStupidNoob

Trả lời

5

K, vì vậy tôi đã tìm ra nó tôi nghĩ, có vẻ như nó hoạt động ngay bây giờ. Hóa ra, vì các mã cho các ký tự là 15 9E 02 00 và 15 9E 00 00, thì không có cách nào để chúng có thể được giữ trong một, một UTF-16 char. Vì vậy, thay vào đó, UTF16 sử dụng các cặp thay thế này, nơi có hai nhân vật khác nhau hoạt động như một 'nguyên tố'. Để nhận các yếu tố, chúng tôi có thể sử dụng:

StringInfo.GetTextElementEnumerator(string fred); 

và điều này trả về một chuỗi với cặp thay thế. Đối xử với nó như một nhân vật.

Xem ở đây:

http://msdn.microsoft.com/en-us/library/system.globalization.stringinfo.aspx

http://msdn.microsoft.com/en-us/library/system.globalization.textelementenumerator.gettextelement.aspx

Hy vọng nó sẽ giúp ai đó: D

0

Khi viết bạn không chỉ định UTF-32 để nó mặc định thành Mã hóa.UTF8.

Từ MSDN:

constructor này tạo ra một StreamWriter với mã UTF-8 mà không có một Byte-Order Mark (BOM), vì vậy phương pháp GetPreamble nó trả về một mảng byte rỗng . Để tạo một StreamWriter sử dụng mã hóa UTF-8 và một BOM, xem xét sử dụng một hàm tạo chỉ định mã hóa, chẳng hạn như StreamWriter (String, Boolean, Encoding).

+0

Điều đó dường như không phải là vấn đề. Tôi đã cập nhật câu hỏi để giúp xóa mọi nhầm lẫn. Mặc dù dù sao đi nữa! – AStupidNoob

0

Tôi nghĩ bạn cần phải chỉ định cùng một mã hóa (Encoding.UTF32) cũng cho số StreamWriter của mình.

EDIT:

Thông thường nó là không cần thiết giữa codepage UTF nhưng tôi cũng sẽ cố gắng này:

Encoding utf8 = Encoding.UTF8; 
Encoding utf32 = Enconding.UTF32; 
byte[] utf8Bytes = utf8.GetBytes(yourText); 
byte[] utf32Bytes = Encoding.Convert(utf8, utf32, utf8Bytes); 
string utf32Text = iso.GetString(utf32Text); 
+0

Tôi có: D, tôi vừa chỉnh sửa câu hỏi.Ngoài ra nó sẽ không thực sự quan trọng anyway, vì bất kỳ ký tự UTF-32 có thể được thể hiện trong UTF-8 hoặc bất kỳ mã hóa Unicode cho vấn đề đó. AFAIK, dù sao đi nữa. – AStupidNoob

+0

@AStupidNoob Tôi chỉ đọc câu trả lời cập nhật và nhận xét của bạn. Nếu bạn biết mã hóa là tập tin đọc và nó là khác hơn UTF32 thì bạn phải đọc nó trong mã hóa ban đầu của nó và chuyển đổi nó thành của riêng bạn muốn trước khi viết nó. – Dummy01

+0

Cảm ơn sự giúp đỡ của bạn một lần nữa. Tôi đã thử đề nghị của bạn, nhưng tôi không thể làm cho nó hoạt động D :. Ngoài ra, tôi nghĩ rằng toàn bộ mục đích của StringReaders và StringWriters là để chuyển đổi giữa các mã hóa. Có lẽ không phải lúc đó. – AStupidNoob

1

tôi đã cố gắng này và nó hoạt động tốt trên máy tính của tôi.

System.IO.StreamReader streamReader = new System.IO.StreamReader("input", true); 
System.IO.StreamWriter streamWriter = new System.IO.StreamWriter("output", false); 

streamWriter.Write(streamReader.ReadToEnd()); 

streamWriter.Close(); 
streamReader.Close(); 

Có thể văn bản bạn nghĩ là UTF32 là không.

+0

Bạn đang sử dụng Visual Studio/Windows? Nó có thể chỉ là mono nếu không. Tôi sẽ thử các chương trình khác để chắc chắn rằng nó thực sự là UTF32, nó chắc chắn trông giống như nó trong một trình soạn thảo hex ... – AStupidNoob

+0

Ok, chúc may mắn. Nhưng mã của bạn đã tạo ra kết quả sai trên máy tính của tôi. –

+1

Ồ, xin lỗi tôi không nhận thấy sự thay đổi trong mã của bạn. Trong tin tức khác, sử dụng visual studio 2012 beta dẫn đến đầu ra chính xác với mã của tôi ... – AStupidNoob

0

Từ phần chú thích của MSDN cho StreamReader's constructor:

constructor này khởi mã hóa theo quy định của các tham số mã hóa , và kích thước bộ đệm nội 1024 byte. Đối tượng StreamReader cố gắng phát hiện mã hóa bằng cách xem ba byte đầu tiên của luồng. Nó tự động nhận dạng UTF-8, Unicode nhỏ gọn và văn bản Unicode lớn cấp nếu tệp bắt đầu với các dấu thứ tự byte thích hợp. Nếu không, mã hóa do người dùng cung cấp được sử dụng. Xem phương thức Encoding.GetPreamble để biết thêm thông tin .

Rất có thể dấu thứ tự byte ở đầu tệp của bạn thực sự chỉ ra UTF 16 (hoặc cái gì đó) và do đó không sử dụng mã UTF 32 được chỉ định rõ ràng.

+0

Chắc chắn tại sao không, tôi sẽ thử sử dụng một số chương trình khác để đảm bảo tôi nhận được BOM chính xác. – AStupidNoob

+0

@AStupidNoob có vẻ như có quá tải hàm xây dựng sẽ không nhìn vào BOM bằng cách thêm tham số boolean, có thể thử nếu bạn không có chương trình khác để kiểm tra. – Tanzelax

+0

Phải, tôi đã nghĩ rằng việc chỉ định mã hóa sẽ đảm bảo nó đã được sử dụng, rõ ràng là không sau đó. Tôi đã làm, tuy nhiên, hãy thử sử dụng các cửa sổ cho việc này và nó đã làm việc. Tuy nhiên, tôi đã không thể xác minh đầu ra UTF32 của nó vì tôi không có bất kỳ chương trình cửa sổ nào chơi tốt với UTF32, vì vậy tôi đổi nó thành đầu ra theo UTF8. – AStupidNoob