2009-02-20 63 views
7

Tôi có một tệp có chứa một số lượng văn bản thuần túy khi bắt đầu theo sau là nội dung nhị phân ở cuối. Kích thước của nội dung nhị phân được xác định bởi một số dòng văn bản thuần túy mà tôi đọc.Đọc chuỗi và nhị phân từ cùng một FileInputStream

Tôi đã sử dụng BufferedReader để đọc các dòng riêng lẻ, tuy nhiên nó không cho thấy phương pháp nào để tham khảo đọc một mảng byte. Các readUTF cho một DataInputStream không đọc tất cả các cách để kết thúc của dòng, và các phương pháp readLine không được chấp nhận.

Sử dụng phần cơ bản FileInputStream để đọc trả về mảng byte trống. Bất kỳ đề xuất về cách đi về điều này?


private DOTDataInfo parseFile(InputStream stream) throws IOException{ 
DOTDataInfo info = new DOTDataInfo(); 
BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); 
int binSize = 0; 
String line; 
while((line = reader.readLine()) != null){ 
    if(line.length() == 0) 
     break; 
    DOTProperty prop = parseProperty(line); 
    info.getProperties().add(prop); 
    if(prop.getName().equals("ContentSize")) 
     binSize = Integer.parseInt(prop.getValue()); 
} 
byte[] content = new byte[binSize]; 
stream.read(content); //Its all empty now. If I use a DataInputStream instead, its got the values from the file 
return info; 
} 
+0

Có thể đăng mã cung cấp cho bạn các mảng trống? Nó không nên làm điều đó ... –

+0

Tôi nghĩ rằng vấn đề là bufferedReader đọc dữ liệu nhị phân là tốt, bởi vì nó đệm dữ liệu. Điều này có nghĩa là không có gì để đọc từ InputStream - do đó kết quả mảng byte rỗng. –

Trả lời

3

Nếu bạn thực sự có một tập tin (chứ không phải là một cái gì đó khó khăn hơn để tìm kiếm trong, ví dụ như một dòng suối mạng) sau đó tôi đề nghị một cái gì đó như thế này:

  • Mở tập tin như một FileInputStream
  • Wrap nó trong InputStreamReader và BufferedReader
  • Đọc văn bản để bạn có thể tìm hiểu xem có bao nhiêu nội dung ở đó là
  • Đóng BufferedReader (sẽ đóng InputStreamReader sẽ đóng FileInputStream)
  • Mở lại tập tin
  • Skip to (tổng chiều dài tập tin - nhị phân chiều dài nội dung)
  • Đọc phần còn lại của dữ liệu như bình thường

Bạn chỉ có thể gọi mark() vào lúc bắt đầu của FileInputStream và sau đó reset()skip() để đến đúng nơi nếu bạn muốn tránh mở lại tệp. (Tôi đang tìm kiếm một số InputStream.seek() nhưng tôi không thể nhìn thấy một - Tôi không thể nhớ là muốn có nó trước đây trong Java, nhưng nó không thực sự có nó? Ick.)

+0

Vâng, có vẻ như con đường để đi tôi giả sử. Nhưng ngoài sự tò mò, nếu đó là một luồng khó tìm kiếm, làm thế nào người ta có thể hiểu được nó? Điều này có vẻ như rất nhiều nỗ lực để những gì tôi nghĩ có thể có một giải pháp trực quan (nhưng khó nắm bắt!). –

+1

Vâng, bit khéo léo đang đọc dữ liệu ký tự mà không "đọc quá" vào dữ liệu nhị phân. Bạn có thể làm điều đó bằng cách đọc một ký tự đơn tại một thời điểm từ một InputStreamReader - Tôi chưa kiểm tra xem nó có đệm hay không - nhưng điều đó sẽ không hiệu quả. (Bạn có thể quấn luồng trong [cont] –

+1

một BufferedInputStream để tránh thực sự chuyển sang OS/đĩa cho mỗi cuộc gọi, phải thừa nhận.) Về cơ bản các tệp định dạng hỗn hợp luôn là một chút đau. Nó không phải là xấu như vậy nếu định dạng bao gồm một tiền tố chiều dài mỗi khi có văn bản: "Các n byte tiếp theo là văn bản" như sau đó bạn biết nơi để dừng lại. –

0

Cách đúng là sử dụng một InputStream của một số hình thức, có lẽ một FileInputStream trừ khi điều này trở thành một rào cản hiệu suất.

Ý của bạn là "Sử dụng FileInputStream cơ bản để đọc trả về mảng byte trống."? Điều này có vẻ rất khó xảy ra và có lẽ là nơi sai lầm của bạn. Bạn có thể cho chúng tôi thấy mã ví dụ bạn đã thử không?

2

Bạn cần sử dụng InputStream. Người đọc dành cho dữ liệu ký tự. Nhìn vào gói input stream của bạn với một DataInputStream, như:

stream=new DataInputStream(new BufferedInputStream(new FileInputStream(...))); 

Các dữ liệu input stream sẽ cung cấp cho bạn nhiều phương pháp hữu ích để đọc các loại dữ liệu khác nhau, và tất nhiên, các phương pháp cơ sở InputStream để đọc byte.

(Đây thực sự là chính xác những gì một máy chủ HTTP phải làm gì để đọc một yêu cầu với nội dung.)


Các readUTF không đọc một dòng, nó đọc một chuỗi đã được viết bằng (sửa đổi) Định dạng UTF8 - tham khảo JavaDoc.

0

Bạn có thể đọc văn bản bằng BufferedReader. Khi bạn biết nơi bắt đầu nhị phân, bạn có thể đóng tệp và mở tệp bằng RandomAccessFile và đọc tệp nhị phân từ bất kỳ điểm nào trong tệp. Hoặc bạn có thể đọc tệp dưới dạng nhị phân và chuyển đổi thành văn bản các phần bạn xác định dưới dạng văn bản. {Sử dụng chuỗi mới (byte, mã hóa)}

4

Bạn có thể sử dụng RandomAccessFile. Sử dụng readLine() để đọc văn bản thuần khi bắt đầu (lưu ý các giới hạn này, như được mô tả trong API) và sau đó readByte() hoặc readFully() để đọc dữ liệu nhị phân tiếp theo.

Sử dụng phần cơ bản FileInputStream để đọc trả về mảng byte trống.

Đó là vì bạn đã bao bọc luồng trong một BufferedReader, có thể đã tiêu thụ tất cả các byte từ luồng khi lấp đầy bộ đệm của nó.

+0

+1 để đề cập đến bộ đệm –

0

Tôi khuyên bạn nên sử dụng DataInputStream.Bạn có các tùy chọn sau:

  • đọc cả văn bản và nội dung nhị phân với DataInputStream
  • Mở một BufferedReader, đọc văn bản và đóng dòng. Sau đó mở một DataInputStream, bỏ qua byte bằng kích thước của văn bản và đọc dữ liệu nhị phân.
1

Than ôi, DataInputStream không được chấp nhận và không xử lý UTF. Nhưng điều này sẽ giúp (nó đọc một dòng từ một dòng nhị phân, mà không có bất kỳ lookahead).

public static String lineFrom(InputStream in) throws IOException { 
    byte[] buf = new byte[128]; 
    int pos = 0; 
    for (;;) { 
     int ch = in.read(); 
     if (ch == '\n' || ch < 0) break; 
     buf[pos++] = (byte) ch; 
     if (pos == buf.length) buf = Arrays.copyOf(buf, pos + 128); 
    } 
    return new String(Arrays.copyOf(buf, pos), "UTF-8"); 
} 
Các vấn đề liên quan