2011-06-30 36 views
5

Tôi đang cố gắng đọc dữ liệu từ luồng nhị phân, một phần trong đó phải được phân tích cú pháp là UTF-8.Đọc cả dữ liệu văn bản và dữ liệu nhị phân từ InputStream

Sử dụng trực tiếp InputStream cho dữ liệu nhị phân và InputStreamReader trên đầu trang cho văn bản UTF-8 không hoạt động khi người đọc đọc trước và làm hỏng dữ liệu nhị phân tiếp theo ngay cả khi được yêu cầu đọc tối đa trong số n ký tự.

Tôi nhận ra câu hỏi này rất giống với Read from InputStream in multiple formats, nhưng giải pháp được đề xuất có cụ thể đối với luồng HTTP, điều này không giúp ích gì cho tôi.

Tôi đã nghĩ chỉ đọc mọi thứ dưới dạng dữ liệu nhị phân và chuyển đổi các phần liên quan thành văn bản sau đó. Nhưng tôi chỉ có thông tin về độ dài của dữ liệu ký tự trong các ký tự chứ không phải theo byte. Vì vậy, tôi cần điều mà đọc nhân vật từ dòng để được nhận thức của mã hóa.

Có cách nào để yêu cầu InputStreamReader không đọc trước hơn cần thiết để đọc số ký tự nhất định không? Hoặc là có một người đọc hỗ trợ cả dữ liệu nhị phân và văn bản với một mã hóa và có thể được chuyển đổi giữa các chế độ này trên bay?

Trả lời

2

Trước tiên, bạn cần phải đọc phần nhị phân. Khi bạn nhận ra một phần byte cần giải mã UTF-8, bạn cần trích xuất các byte đó và giải mã nó.

DataInputStream dis = 
// read a binary type. 
int num = dis.readInt(); 
int len = dis.readUnsignedShort(); 
// read a UTF-8 portion. 
byte[] bytes = new byte[len]; 
dis.readFully(bytes); 
String text = new String(bytes, "UTF-8"); 
// read some binary 
double d = dis.readDouble(); 
+1

Vấn đề là, với UTF8, số byte có thể khác với số ký tự. Vì vậy, tôi sẽ cần phải tìm ra số lượng các ký tự nhiều byte trong chuỗi, đọc thêm byte và chuyển đổi một lần nữa và làm điều này hơn và hơn cho đến khi các con số phù hợp. – tajmahal

+0

Tôi muốn nói định dạng của bạn không dễ giải mã và tôi sẽ sửa nó nếu bạn có thể. Tuy nhiên, bạn có thể phân tích cú pháp UTF-8 nếu bạn biết số ký tự. (Nhưng việc gửi số byte thực tế sẽ đơn giản hơn nhiều) –

+0

Cách tiếp cận khác là đọc nhiều dữ liệu hơn mức cần thiết. Lấy số lượng ký tự mong đợi, ví dụ: substring() và chuyển đổi sang UTF-8 để xác định độ dài. Sử dụng dấu() và đặt lại() và đọc độ dài mà bạn biết. (Điều này chỉ hoạt động nếu mã hóa UTF-8 giống hệt nhau: | ví dụ: byte nul \ 0 được mã hóa theo hai cách khác nhau.(như các nhân vật khác có thể) –

2

Tôi nghĩ rằng bạn không nên sử dụng StreamReader. Độc giả đối phó với văn bản nhưng bạn đối phó với văn bản và dữ liệu nhị phân với nhau.

Không có cách nào. Bạn phải đọc bộ đệm nhị phân và tự diễn giải định dạng của mình, tức là tìm vị trí trích xuất văn bản byte và chuyển đổi chúng thành Chuỗi.

Để đơn giản hóa tác vụ này, tôi khuyên bạn nên tạo lớp của riêng bạn (giả sử ProtocolRecord.) Nó phải là Serializable. Nó sẽ chứa tất cả các trường của bạn. Bây giờ bạn có 2 tùy chọn:

(1) đơn giản - sử dụng cơ chế tuần tự hóa java. Trong trường hợp này, bạn chỉ cần quấn luồng của bạn với DataInputStream để đọc và DataOutputStream để viết và sau đó đọc/ghi các đối tượng của bạn. Nhược điểm của phương pháp này là bạn không thể kiểm soát giao thức của mình.

(2) tự mình thực hiện các phương thức readObject() và writeObject(). Bây giờ sử dụng DataInputStream và DataOutputStream như đã giải thích ở trên. Trong trường hợp này, bạn phải thực hiện giao thức tuần tự hóa nhưng ít nhất nó được đóng gói trong lớp của bạn.

Nó nghĩ rằng DataInputStream là những gì bạn cần.

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