2010-07-14 40 views
5

Tôi biết cấu trúc tập tin, cho rằng cấu trúc này là thế này:Đọc dữ liệu có cấu trúc từ tệp nhị phân -?

[3-bytes long int],[1-byte long unsigned integer],[4-bytes long unsigned integer] 

Vì vậy, các tập tin có chứa chuỗi các hồ sơ đó.

Cách tốt nhất để phân tích cú pháp tệp như vậy trong Java là gì?

Giả sử, chúng ta có thể xác định một mảng byte [] có chiều dài tổng thể và đọc nó với InputStream, nhưng sau đó chuyển đổi các giá trị con của nó thành các giá trị số nguyên chính xác?

Điều đầu tiên, giá trị byte trong java được ký, chúng tôi cần giá trị chưa ký trong trường hợp của chúng tôi. Điều tiếp theo, có phương pháp hữu ích cho phép chuyển đổi một mảng phụ của byte, nói, byte từ 1-st đến 4-th thành một giá trị số nguyên chính xác?

Tôi biết chắc chắn, có chức năng gói & giải nén trong Perl, cho phép bạn biểu diễn một chuỗi byte dưới dạng biểu thức, giả sử "VV" có nghĩa là 2 giá trị int dài chưa ký. Bạn xác định một chuỗi như vậy và cung cấp chuỗi đó làm đối số cho các gói gói hoặc giải nén cùng với các byte được đóng gói/giải nén. Có những thứ như vậy trong Java/Apache libs không?

+0

thể trùng lặp của [Cách tốt nhất để đọc các tập tin nhị phân có cấu trúc với Java] (http://stackoverflow.com/questions/277944/best-way-to-read-structured -binary-files-with-java) –

Trả lời

1

Bạn có thể thực hiện việc này bằng cách sử dụng DataInputStream. Đã một thời gian kể từ khi tôi thực hiện nhiều phát triển như thế này, nhưng mẹo tôi nhớ là nếu có một kết hợp sai lệch trở kháng giữa định dạng đầu vào của bạn và kiểu dữ liệu của ngôn ngữ bạn sẽ cần để tạo byte dữ liệu theo byte . Trong trường hợp này, có vẻ như bạn sẽ cần phải làm điều đó bởi vì cấu trúc dữ liệu có cấu trúc có kích thước kỳ lạ.

Để cung cấp cho bạn một ví dụ để đọc các bản ghi đầu tiên bạn có thể cần phải làm một cái gì đó như thế này (tôi đang sử dụng a, b, và c cho các thuộc tính của các bản ghi)

DataInputStream dis = ... 

int a = 0; 
a = dis.readByte(); 
a = a << 8;   
a = a | dis.readByte(); 
a = a << 8; 
a = a | dis.readByte(); 

short b = 0; 
b = dis.readByte(); 

long c = 0; 
c = dis.readByte(); 
c = c << 8; 
c = c | dis.readByte(); 
c = c << 8; 
c = c | dis.readByte(); 
c = c << 8; 
c = c | dis.readByte(); 

Rõ ràng, điều này mã có thể được thắt chặt bằng cách kết hợp một số báo cáo, nhưng bạn có được ý tưởng chung. Những gì bạn có thể nhận thấy là cho mỗi thuộc tính được đọc, tôi phải sử dụng một nguyên thủy lớn hơn cần thiết để không có bất kỳ lỗi tràn nào. Để tham khảo, trong Java:

  • byte = 1 byte
  • ngắn = 16 bit, 2 byte
  • int = 32 bit, 4 byte
  • dài = 64 bit, 8 byte
3

Giống như ví dụ @Bryan Kyle nhưng ngắn hơn. Tôi thích ngắn hơn, nhưng điều đó không có nghĩa là rõ ràng hơn, bạn quyết định. ;) Lưu ý: readByte() được ký và sẽ có kết quả không mong muốn nếu không được che dấu bằng 0xFF.

DataInputStream dis = ... 

// assuming BIG_ENDIAN format 
int a = dis.read() << 16 | dis.read() << 8 | dis.read(); 
short b = (short) dis.read(); 
long c = dis.readInt() & 0xFFFFFFFFL; 

hoặc

ByteBuffer bb = 
bb.position(a_random_postion); 
int a = (bb.get() & 0xFF) << 16 | (bb.get() & 0xFF) << 8 | (bb.get() & 0xFF); 
short b = (short) (bb.get() & 0xFF); 
long c = bb.readInt() & 0xFFFFFFFFL; 
Các vấn đề liên quan