2010-05-26 34 views
5

Sử dụng C#, tôi cần đọc tệp nhị phân được đóng gói được tạo bằng FORTRAN. Các tập tin được lưu trữ trong một định dạng "không định dạng tuần tự" như mô tả ở đây (khoảng một nửa chiều xuống trang trong "không định dạng tuần tự Files" mục):phân tích nội dung khỏi cấu trúc trong tệp nhị phân

http://www.tacc.utexas.edu/services/userguides/intel8/fc/f_ug1/pggfmsp.htm

Như bạn có thể nhìn thấy từ URL, tập tin được tổ chức thành "khối" của 130 byte hoặc ít hơn và bao gồm 2 byte dài (chèn bởi trình biên dịch FORTRAN) xung quanh mỗi đoạn.

Vì vậy, tôi cần tìm một cách hiệu quả để phân tích cú pháp tải tệp thực tế khỏi định dạng do trình biên dịch chèn vào.

Khi tôi đã trích xuất tải trọng thực tế từ tệp, tôi sẽ cần phải phân tích cú pháp nó thành các loại dữ liệu khác nhau của nó. Đó sẽ là bài tập tiếp theo.

Suy nghĩ đầu tiên của tôi là phải lật toàn bộ tệp vào một mảng byte bằng cách sử dụng File.ReadAllBytes. Sau đó, chỉ cần lặp qua các byte, bỏ qua định dạng và chuyển dữ liệu thực tế sang mảng byte thứ hai.

Cuối cùng, mảng byte thứ hai đó phải chứa nội dung tệp thực sự trừ đi tất cả định dạng mà sau đó tôi cần quay lại để có được những gì tôi cần.

Vì tôi khá mới đối với C#, tôi nghĩ có thể có cách tốt hơn, được chấp nhận hơn để giải quyết vấn đề này.

Ngoài ra, trong trường hợp nó rất hữu ích, những tập tin này có thể là khá lớn (nói 30MB), mặc dù hầu hết sẽ nhỏ hơn nhiều ...

Trả lời

1

Một cách để đọc các tập tin như thế này là kỷ lục của kỷ lục (ví dụ, đọc độ dài byte và sau đó là đoạn dữ liệu, xây dựng một danh sách các bản ghi, mà chỉ là mảng byte). Việc thu thập các bản ghi sau đó được chuyển đến các phân tích cú pháp tiếp tục.

Tuy nhiên, nếu bạn đang ở chế độ 4.0, có new class để ánh xạ tệp sẽ hiệu quả hơn nhưng hoạt động tương tự như ReadAllBytes.

Nếu bạn đang sử dụng ReadAllBytes hoặc MemoryMappedFile, bạn nên tạo một "chỉ mục" trong bộ nhớ vào tệp nhị phân lớn bằng cách phân tích cú pháp tất cả độ dài bản ghi trước tiên. Điều này đặc biệt hữu ích nếu bạn chỉ cần một số hồ sơ nhất định.

+0

Cảm ơn. Dựa trên các ý kiến ​​của bạn, tôi đã viết một số mã tải tệp của tôi vào một mảng byte và tạo ra một mảng byte thứ hai, sạch (không có các dấu hiệu độ dài).Bây giờ tôi đang cố gắng phân tích nó thành các giá trị vô hướng khác nhau bằng cách sử dụng BitConverter, mặc dù nó có vẻ hơi xấu xí vì tôi cần phải duy trì con trỏ của riêng mình vào mảng khi tôi chuyển đổi nó. Giả sử tôi tiếp tục với mảng byte, có cách nào tốt hơn để có được các vô hướng khác nhau từ nó? Ồ, và tôi không sử dụng 4.0 ... –

+0

Có thể bọc mảng byte vào một 'MemoryStream' và sử dụng một' BinaryReader'. 'BinaryReader' nhớ vị trí riêng của nó, do đó bạn không cần. –

0

Thay vì lặp qua các byte, hãy xem System.IO.BinaryReader. Mở tệp dưới dạng FileStream, bọc nó trong một BinaryReader và bạn có thể đọc trực tiếp các loại nguyên thủy từ tệp đó, với con trỏ luồng theo dõi tỷ lệ chênh lệch của bạn thành đốm màu. Bạn có thể phải tự mình tính đến các loại kết thúc và tùy chỉnh, có thể xây dựng các phương thức mở rộng của riêng bạn cho BinaryReader trên đầu trang của phương thức của nó để đọc các byte riêng lẻ.

Nếu bạn cần dữ liệu trong một mảng byte, bạn vẫn có thể sử dụng BinaryReader nếu bạn quấn mảng trong một MemoryStream trước tiên.

Với các tệp lớn, tôi chỉ đạo rõ ràng là File.ReadAllBytes. FileStream nên đệm cho bạn, và gợi ý của Stephen cho việc sử dụng các tệp ánh xạ bộ nhớ âm thanh như một sự thay thế phức tạp hơn (có thể hiệu quả hơn), đặc biệt nếu bạn cần thực hiện lần thứ hai để định dạng.

+0

Cảm ơn. Vấn đề tôi thấy với sau này trực tiếp với BinaryReader là dữ liệu bị ô nhiễm với chiều dài đánh dấu (như được nêu trong URL của bài gốc). Vì vậy, tôi không thể chỉ đơn giản là bắt đầu đọc nguyên thủy của tôi như là các dấu hiệu chiều dài sẽ đi lên con trỏ dòng. Do đó, nó có vẻ sạch hơn trước hết quét dữ liệu của các điểm đánh dấu độ dài và sau đó xử lý nó trong bước thứ hai. Tuy nhiên, điều đó không có nghĩa là hãy rót toàn bộ thứ vào bộ nhớ trước. Bạn có thấy một cách dễ dàng để tránh xa các điểm đánh dấu độ dài và sử dụng BinaryReader trong một lần truyền không? –

+0

Ah, tôi hiểu rồi. Vâng, bây giờ bạn có mã để tạo dữ liệu không được phân loại, thay vì sử dụng BitConverter, bạn có thể xây dựng MemoryStream từ mỗi mảng, nó sẽ xử lý vấn đề con trỏ mảng (MemoryStream có một hàm tạo để gói mảng hiện có, thay vì phân bổ riêng nó) . Sau đó bọc MemoryStream trong BinaryReader. – shambulator

+0

Ah, bây giờ có vẻ đầy hứa hẹn (MemoryStream được bao bọc trong một BinaryReader). Hãy để tôi xem những gì tôi có thể làm việc. Cảm ơn bạn. –

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