2009-12-21 28 views
5

Tôi đã viết thư viện C++ để lưu dữ liệu của tôi (tập hợp các cấu trúc tùy chỉnh, v.v.) vào tệp nhị phân. Tôi hiện đang sử dụng (ví dụ: tạotiêu thụ) các tệp cục bộ, trên máy tính Windows (XP) của tôi. Để đơn giản, hãy nghĩ đến thư viện ở hai phần: một biên tập (Tạo tệp) và trình đọc hoặc người tiêu dùng (chỉ cần đọc dữ liệu từ tệp).Tệp nhị phân và khả năng tương thích nền tảng chéo

Gần đây, mặc dù tôi muốn cũng tiêu thụ (ví dụ: đọc) các tập tin dữ liệu tôi đã tạo trên máy XP của tôi, trên máy tính Linux của tôi. Tôi phải chỉ ra ở giai đoạn này là cả hai máy tính đều là máy tính cá nhân (vì vậy có cùng số endianess, v.v.).

Tôi có thể xây dựng trình đọc (và biên dịch cho Linux [Ubuntu 9.10 chính xác]), vì tôi là người tạo thư viện. Câu hỏi của tôi, trước khi tôi bắt tay xuống con đường này (xây dựng người đọc vv) là:

Giả sử tôi đã thành công xây dựng người đọc cho Linux,

Tôi có thể chỉ cần sao chép accross, tập tin đã được tạo trên windows (XP) máy tính đến máy Linux (Ubuntu 9.10) và sử dụng trình đọc Linux để đọc thành công tệp đã sao chép?

+0

Bạn phải xác định ý nghĩa của từ "tệp nhị phân". Bạn có viết những thứ như 'struct' data, vv, bằng cách sử dụng' fwrite'? Bạn có phân hủy mọi thứ thành byte và sau đó ghi dữ liệu? –

+1

Có gì với tất cả các SHOUTING? Bạn có thể sử dụng dấu sao cho ** nhấn mạnh ** và nó dễ đọc hơn ... – danio

+0

@danio anh ấy đến từ DOS, Ở ĐÂU TẤT CẢ CÁC ĐIỀU KHOẢN VỐN – zeitue

Trả lời

14

Đối với các tập tin là nhị phân tương thích:

  • endianness phải phù hợp (vì nó làm cho bạn)
  • bitfield để đóng gói phải giống
  • kích cỡ và signedness các loại phải giống nhau
  • trình biên dịch phải đưa ra quyết định như vậy về đệm và liên kết

Đó chắc chắn có thể f hoặc tất cả những điều kiện này được hoàn thành, hoặc để bạn không xảy ra để đánh bất kỳ trường hợp nào mà họ không phải là. Ít nhất, mặc dù, tôi muốn thêm một số kiểm tra sanity và/hoặc thành viên sentinel để phát hiện các vấn đề.

+0

Xin chào moonshadow, cảm ơn vì phản hồi. Bạn có thể giải thích thêm một chút nữa không - khi bạn có thời gian, sử dụng một lớp đơn giản có chứa một tiêu chuẩn :: vector Tôi sẽ có thể hiểu một cách phi thường, ý của bạn là kiểm tra sanity và/hoặc thành viên sentinel. Cách duy nhất tôi có thể nghĩ đến việc triển khai các kiểm tra này là sử dụng các hằng số được định nghĩa trong limits.h - đó là ý của bạn? - hoặc có thể bạn có một cách tiếp cận thanh lịch hơn? –

+0

Ngoài ra, tôi không chắc chắn làm thế nào để kiểm tra xem các yêu cầu 2, 3 và 4 (mà bạn liệt kê ở trên) có đúng không. Tôi xây dựng bằng cách sử dụng VS2008 trên XP, và sử dụng gcc 4.4.1 trên Ubuntu - bất kỳ lời khuyên nào về cách tôi có thể kiểm tra những yêu cầu này KHÔNG bị vi phạm? –

+2

@Stick it: Bởi "thành viên sentinel", tôi có nghĩa là sắp xếp các cấu trúc cấp cao nhất được ghi vào tệp của bạn để chứa thành viên có giá trị không đổi đã biết và cũng đặt một ở cuối tệp; tại thời gian tải, kiểm tra xem các thành viên này có chứa giá trị bạn mong đợi hay không - điều này sẽ bắt gặp các vấn đề với kích thước/padding khác nhau giữa các trình biên dịch. – moonshadow

2

Tệp nhị phân phải tương thích trên các máy có cùng độ dài cuối cùng.

Vấn đề bạn có thể có trong mã của bạn là kích thước của int, bạn không nhất thiết có thể giả định rằng trình biên dịch trên các hệ điều hành khác nhau có cùng kích thước int. Vì vậy, hoặc sao chép khối byte và quăng, hoặc int16 sử dụng, int32, vv

1

Nếu:

  • các máy có endianess cùng (như bạn nói rằng họ có) và
  • bạn làm mở luồng ở chế độ nhị phân, dưới dạng chế độ văn bản có thể làm những điều thú vị, ví dụ: với dòng kết thúc và
  • bạn đã được lập trình sạch do đó bạn không vấp ngã trên những thứ thực hiện xác định như sắp xếp, kiểu dữ liệu kích thước, và đóng gói struct,

thì có, các file của bạn nên được cầm tay.

Điểm dấu đầu dòng thứ ba là điều làm cho định dạng tệp trở thành "di động". Tùy thuộc vào loại dữ liệu bạn có trong cấu trúc của bạn, nó có thể rất dễ dàng hoặc một chút khó khăn. Bitfields hoặc dữ liệu được diễn giải lại từ một loại khác đặc biệt khó khăn.

1

Bạn có thể xem xét việc xem Boost Serialization Library. Rất nhiều suy nghĩ đã được đưa vào nó, và nó sẽ xử lý nhiều khả năng không tương thích nền tảng tiềm năng cho bạn. Tất nhiên, có thể là nó quá mức cần thiết cho trường hợp sử dụng cụ thể của bạn, đặc biệt nếu bạn đã có các nhà văn của mình & độc giả được triển khai.

1

Cấu trúc là không định dạng tệp và bạn không nên cố gắng sử dụng chúng như vậy.

Khi cố gắng làm cho cấu trúc hoạt động với freadfwrite, có một số lượng lớn các hacks để làm cho nó hoạt động. Bạn có các số nguyên byte-swap để bạn có thể chia sẻ các tệp giữa các máy nhỏ và cuối lớn. Bạn thay đổi cấu trúc của mình để sử dụng các kiểu số nguyên cố định chiều rộng, vì vậy bạn có thể chia sẻ giữa các máy với các kích thước từ khác nhau (chẳng hạn như giữa các máy x86 và x64). Bạn thêm các pragmas cho trình biên dịch cụ thể để kiểm soát phần đệm của các cấu trúc để chia sẻ giữa các phiên bản trình biên dịch.

Nó hoạt động, nhưng nó xấu xí. Chưa kể, dễ mắc sai.

Giống như đề xuất trong The byte order fallacy, một ý tưởng tốt hơn là viết mã để đọc/ghi các trường riêng lẻ. Bằng cách viết mã của riêng bạn, bạn có thể đảm bảo không có đệm, và bạn có thể chọn kích thước nguyên một cách độc lập với kích thước cục bộ của số nguyên và bạn có thể hỗ trợ cả hai kết thúc mà không cần trao đổi byte (bằng cách đọc/ghi byte của một số nguyên riêng biệt).

Không giống như cách tiếp cận hacky, khó có thể sai. Hơn nữa, bởi vì bạn không dựa vào bất kỳ trình biên dịch hoặc hành vi cụ thể kiến ​​trúc, hoặc mã của bạn sẽ làm việc trên tất cả các trình biên dịch và kiến ​​trúc, hoặc không có. Nếu bạn làm đúng, bạn không nên có bất kỳ lỗi nền tảng cụ thể nào.

Có một nhược điểm; đọc/ghi riêng các trường sẽ chậm hơn so với chỉ sử dụng fread/fwrite trực tiếp. Bạn có thể thiết lập bộ đệm (uint8_t buffer[]) và ghi toàn bộ dữ liệu vào đó, sau đó viết mọi thứ cùng một lúc, điều này có thể hữu ích, nhưng nó vẫn sẽ chậm hơn (vì bạn vẫn phải di chuyển các trường vào bộ đệm tại một thời điểm), nhưng đối với hầu hết các mục đích, nó vẫn sẽ đủ nhanh (ngoại lệ là các hệ thống nhúng/thời gian thực hoặc tính toán hiệu năng cực cao).

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