Viết ở đầu tập tin một cái gì đó bạn chỉ biết ở cuối


9

Bối cảnh: Tôi đang viết mã C điều khiển vi mô để viết tệp EBML. EBML giống như một XML nhị phân với các phần tử lồng nhau, nhưng thay vì các thẻ bắt đầu và kết thúc, có ID bắt đầu, độ dài và sau đó là dữ liệu. Tôi đang viết điều này vào Flash bên ngoài trong một ứng dụng năng lượng thấp, vì vậy tôi muốn giữ cho các truy cập flash ở mức tối thiểu. Bộ nhớ cũng bị giới hạn, bởi vì không có gì là dễ dàng.

Khi tôi có thể giữ toàn bộ phần tử EBML trong bộ nhớ, thì việc tạo nó trở nên dễ dàng vì tôi có thể quay lại và điền vào độ dài của mỗi phần tử sau khi tôi biết độ dài đó là bao nhiêu. Vấn đề là phải làm gì khi tôi không thể giữ toàn bộ thành phần trong bộ nhớ. Các tùy chọn tôi thấy là:

  • Viết những gì tôi biết, sau đó quay lại và thêm độ dài (dễ nhất, nhưng thêm nhiều truy cập flash hơn tôi muốn)
  • Tính toán độ dài của mỗi phần tử trước khi tôi bắt đầu viết nó (tương đối dễ, nhưng nhiều thời gian xử lý)
  • Chuyển đổi chế độ khi bộ nhớ của tôi đầy, để sau đó tôi tiếp tục thông qua dữ liệu, nhưng chỉ để tính độ dài cho các phần tử đã được dành riêng trong bộ nhớ. Sau đó viết những gì tôi có trong bộ nhớ, và quay lại và tiếp tục xử lý dữ liệu từ nơi tôi rời đi. (Tùy chọn yêu thích của tôi cho đến nay)
  • Cung cấp cho các phần tử độ dài trường hợp tối đa hoặc tệ nhất khi chúng cần được viết và độ dài cuối cùng của chúng chưa được biết. (Dễ dàng hơn ở trên, nhưng có thể gây phản tác dụng và lãng phí không gian)

Câu hỏi: Có vẻ như đây là một vấn đề tương đối phổ biến mà mọi người đã nghĩ đến. Tôi biết nó cũng có thể xảy ra khi hình thành một số gói dữ liệu. Có một kỹ thuật tốt hơn / phổ biến hơn / được chấp nhận hơn mà tôi đang thiếu ở đây không? Hay chỉ là một số thuật ngữ cho vấn đề mà tôi có thể tìm kiếm?


1
/ sccs hoạt động theo cách này: nó ghi tổng kiểm tra tất cả các byte vào đầu tệp sau khi viết xong. Hoạt động tốt trên các Unix có thể thực hiện các thao tác tệp cần thiết về nguyên tử (ví dụ Solaris) và gây ra các vấn đề lẻ tẻ kỳ lạ trên Unix không thể làm được điều đó, ví dụ: Linux
gnat

Câu trả lời:


2

Nếu bạn không biết tải trọng của mình sẽ kéo dài bao lâu, điều đó hiếm khi gây lo lắng ngay cả khi bạn không thể nhớ vị trí và lấp đầy chiều dài sau đó:

Chỉ cần ghi lại "kích thước không xác định".

Tính năng đó phụ thuộc vào tải trọng bao gồm các phần tử EBML và phần tử sau đây không phải là phần tử con hợp lệ.

Nếu bạn muốn, sau này bạn có thể hợp thức hóa EBML ngoại tuyến một cách thuận tiện theo bất kỳ cách nào bạn muốn, ví dụ: "không có kích thước không xác định, kích thước tối thiểu" hoặc "kích thước tối thiểu, tránh kích thước không xác định".


Tham khảo Dự thảo EBML RFC trên matroska.org để biết chi tiết.


Điều đó thật tuyệt! Đó là điều mà tôi không nhận thức được và nó tránh được vấn đề cốt lõi, nhưng tôi vẫn thích hướng dẫn về một cách tốt để giải quyết vấn đề cốt lõi. Sử dụng một yếu tố kích thước không xác định có vẻ như có thể hạn chế khả năng tương thích trong tương lai, vì phần mềm cũ sẽ sớm thoát khỏi các yếu tố mới.
pscheidler

Bạn cần DTD đúng hoặc bạn thực sự không thể giải mã EBML. Chà, nếu tất cả các yếu tố không xác định có kích thước bạn có thể bỏ qua chúng, nhưng như vậy đã đủ chưa? Chỉ cần xử lý hậu kỳ bất kỳ EBML nào bạn muốn lưu trữ ngoại tuyến nếu có.
Ded repeatator

Chúng tôi đang sử dụng lược đồ riêng của chúng tôi, sẽ mở rộng. Nó đã được thiết kế với kiến ​​thức rằng phần mềm cũ hơn cuối cùng có thể phải bỏ qua một số dữ liệu. Nhưng đây là một tính năng tuyệt vời của EBML mà tôi không biết, vì vậy tôi chấp nhận câu trả lời.
pscheidler

0

Nếu một phần tử duy nhất có số lượng phụ cố định quá lớn, thì có lẽ bạn nên thử chia nó trong lược đồ. Tôi không biết định dạng này, nhưng hầu hết có lẽ bạn có thể xác định chiều dài tối đa trong nó.

Đối với các chuỗi, bạn có thể cố gắng xác định số lượng phụ tối đa và "luồng" còn lại trong tệp tiếp theo

Đối với các phần tử có khả năng vượt quá kích thước bộ nhớ tối đa, hãy chuẩn bị một ngăn xếp chứa các cặp: vị trí chiều dài phần tử dành riêng và bộ đếm độ dài. Trên pop lưu bộ đếm hiện tại trong điểm đánh dấu hiện tại và thêm giá trị của nó vào bộ đếm tiếp theo.

Nói chung, cố gắng tối thiểu hóa số lượng các yếu tố quá lớn


Chà, anh ta có thể làm điều đó cho các yếu tố EBML của riêng mình, nhưng điều đó vẫn không giúp anh ta với yếu tố cha mẹ.
Ded repeatator

Ý tưởng của bạn sẽ hoạt động, nhưng tôi muốn tạo ra một hệ thống có thể xử lý các phần tử lớn, thay vì ràng buộc lược đồ để nó tránh các phần tử lớn.
pscheidler

Giải pháp này cũng sẽ làm việc cho các phần tử lớn, chỉ cần cẩn thận với kích thước ngăn xếp. Và nếu nói đến lược đồ ... hãy nghĩ về nó như một ngôn ngữ mà các ứng dụng của bạn đang sử dụng, nếu một cái không thể xử lý một thứ phức tạp, thì cái kia sẽ điều chỉnh hoặc cần một người dịch. Nhiều nhà phát triển (ít nhất là những người phát triển C / C ++ mà tôi biết) có xu hướng tránh các thay đổi về lược đồ / thiết kế giống như nó là một đám cháy, sau đó dẫn đến một hệ thống kém. Nếu thành phần khác không thể điều chỉnh, thì có lẽ nó bị phân hủy / thiết kế kém. Nếu có những lý do khác để không thay đổi, thì có lẽ bạn nên xem xét việc sử dụng một phần cứng khác
Whoot

0

HÔN và YAGNI.
Chọn tùy chọn # 1 và nếu nó trở thành một vấn đề thực sự - chỉ sau đó nhắc lại về nó.

Ít nhất là đối với các trường hợp sử dụng tương tự có định dạng nhị phân tương tự, khi chỉ cần điền một vài giá trị theo cách như vậy, đây là giải pháp đơn giản / dễ nhất / tốt nhất. Nếu bạn phải làm điều này trên từng khối dữ liệu - thì đó có thể là một lỗ hổng trong kiến ​​trúc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.