Написання на початку файлу те, що ви знаєте лише в кінці


9

Передумови: Я пишу код мікроконтролера C, щоб написати файл EBML. EBML - це як бінарний XML з вкладеними елементами, але замість початкових і кінцевих тегів є ідентифікатор початку, довжина, а потім дані. Я записую це у зовнішній Flash у програмі малої потужності, тому я хотів би звести доступ до спалаху до мінімуму. Пам'ять також обмежена, тому що ніколи не буває просто.

Коли я можу зберігати весь елемент EBML в пам’яті, тоді генерувати його легко, тому що я можу повернутися назад і заповнити довжину кожного елемента після того, як я знаю, що це за довжина. Проблема полягає в тому, що робити, коли я не можу утримувати весь елемент в пам'яті. Я бачу такі варіанти:

  • Напишіть те, що я знаю, а потім поверніться та додайте довжини (найпростіше, але додайте більше флеш-доступу, ніж я хочу)
  • Обчисліть довжину кожного елемента перед тим, як почати його писати (порівняно легко, але багато процесорного часу)
  • Перемикайте режими, коли моя пам’ять заповниться, щоб потім продовжувати дані, але тільки для обчислення довжини елементів, які вже зарезервовані в пам'яті. Потім запишіть те, що у мене є, і поверніться та продовжуйте обробляти дані, звідки я зупинився. (Мій улюблений варіант поки що)
  • Надайте елементам максимальну або найгіршу довжину випадку, коли їх потрібно записати, а їх кінцева довжина ще не відома. (Легше, ніж вище, але це може призвести до пожежі та втратити місце)

Питання: Схоже, це має бути відносно поширеним питанням, про яке люди думали. Я знаю, що це може статися і при формуванні деяких пакетів даних. Чи є краща / більш поширена / більш прийнята методика, якої я тут відсутній? Або просто якісь умови для проблеми, які я можу шукати?


1
/ sccs працює таким чином: він записує контрольну суму всіх байтів на початку файлу після написання. Відмінно працює в Unixes, який може виконувати необхідні операції з файлами атомно (наприклад, Solaris) і викликає дивні спорадичні проблеми в Unixes, які не можуть цього зробити, наприклад Linux
gnat

Відповіді:


2

Якщо ви не знаєте, як довго триватиме ваша корисна навантаження, це рідко викликає занепокоєння, навіть якщо ви не можете запам'ятати позицію та заповнити довжину пізніше:

Просто занотуйте "невідомий розмір".

Ця функція залежить від корисного навантаження, що складається з EBML-елементів, і наступний елемент не є дійсним дочірнім елементом.

Якщо ви хочете, пізніше ви можете канонізувати отриманий EBML в автономному режимі будь-яким способом, наприклад, "невідомий розмір, мінімальний розмір" або "мінімальний розмір, уникайте невідомих розмірів".


Для детальної інформації зверніться до проекту проекту RFC EBML на matroska.org .


Це чудово! Це те, про що я не знав, і це дозволяє уникнути основної проблеми, але я все-таки хотів би вказати про хороший спосіб вирішення основної проблеми. Використання елемента невідомого розміру здається, що це може обмежити сумісність у майбутньому, оскільки старе програмне забезпечення передчасно вийде на нові елементи.
pscheidler

Вам потрібен правильний DTD або ви не можете реально розшифрувати EBML. Що ж, якщо всі невідомі елементи розміру, ви можете пропустити їх, але чи цього достатньо? Просто обробіть будь-який EBML, який ви хочете зберігати в автономному режимі, якщо він є.
Дедуплікатор

Ми використовуємо власну схему, яка розшириться. Він був розроблений з урахуванням того, що з часом старе програмне забезпечення може пропустити деякі дані. Але це чудова особливість EBML, про яку я не знав, тому приймаю відповідь.
pscheidler

0

Якщо один елемент із фіксованою кількістю субелементів занадто великий, то, можливо, вам слід спробувати поділити його на схемі. Я не знаю цього формату, але, швидше за все, ви можете визначити максимальну довжину в ньому.

Для послідовностей ви можете спробувати визначити максимальну кількість підрядів і "потік", що залишиться в наступному файлі

Для елементів, що потенційно перевищують максимальний об'єм пам'яті, підготуйте стек, що містить пари: зарезервоване розташування довжини елемента та лічильник довжини. На попі збережіть поточний лічильник у поточному маркері та додайте його значення до наступного лічильника.

Взагалі намагайтеся мінімізувати кількість занадто великих елементів


Ну, він, ймовірно, міг би це зробити для власних елементів EBML, але це все ще не допомагає йому з батьківським елементом.
Дедуплікатор

Ваша ідея спрацювала б, але я б швидше створив систему, яка може обробляти великі елементи, а не обмежувати схему, щоб вона уникала великих елементів.
pscheidler

Це рішення підійде і для великих елементів, просто будьте обережні з розміром стека. А якщо мова йде про схему ... подумайте про це як про мову, якою користуєтеся ваші програми, якщо одна не може обробити складну, то інша повинна налаштуватись або потрібен перекладач. Багато розробників (принаймні C / C ++ тих, кого я знаю), як правило, уникають змін схеми / дизайну, як-от пожежа, що згодом призводить до поганої системи. Якщо інший компонент не в змозі налаштувати, можливо, він погано розкладається / проектується. Якщо є інші причини не змінюватись, то, ймовірно, слід подумати про використання іншого обладнання
Whoot

0

KISS та YAGNI.
Виберіть варіант №1, і якщо це стане справжньою проблемою - лише потім повторіть його.

Принаймні, для подібних випадків використання з подібними бінарними форматами, коли таким чином потрібно було заповнити лише пару значень, це найпростіший / найпростіший / найкращий варіант рішення. Якщо вам доведеться робити це на кожному фрагменті даних - це може бути вадою в архітектурі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.