Чи є якась небезпека написання необроблених байтів у файл? [зачинено]


12

Я працюю над проблемою в програмуванні Pearls - конкретно, над реалізацією програми, яка сортує файл, що містить, щонайменше, 10 000 000 цілих чисел (стовпець 1, проблема 3). Оскільки в книзі не вказано, як слід зберігати дані у файлі, я розглядаю можливість зберігання цілих чисел як необроблених байтів (є деякі інші обмеження, які роблять необроблені байти хорошим варіантом). Я ніколи раніше не працював на такому низькому рівні, тому хочу знати, чи є щось небезпечне, на що я повинен стежити. Чи потрібно мені турбуватися про випадкове використання якоїсь послідовності в кінці файлу, коли я записую необроблені байти у файл, наприклад?

Редагувати:

Зараз я усвідомлюю, наскільки широким було моє питання. Я справді мав на увазі проблеми більш катастрофічного типу, як-от випадкове перезапис інших файлів на диску. Вибачте, спочатку я не був яснішим.


6
Зауважте, що програмування перлів - це дуже стара книга; ви могли легко прочитати цілі 10 ^ 7 цілих чисел у пам'яті на сучасній настільній машині, зробіть сортування та запишіть її ще раз. Щоб отримати початковий пункт цієї глави, обмежте кількість, яку ви прочитали в будь-який час, на частку від загальної кількості. Або збільшити розмір файлу приблизно до 10 ^ 10 цілих чисел.
Калеб

3
Насправді, коли я чую слово "небезпечно", я думаю про речі, які змушують мій ПК вибухнути, видалити мої банківські рахунки чи щось подібне. І я здогадуюсь, це, ймовірно, безпечно припустити, що - поки ваша програма не використовується для управління Airbus або електростанцією, нічого, що насправді є "небезпечним", не станеться, коли ви спробуєте те, що маєте на увазі.
Doc Brown


2
@delnan Років тому, коли міф про характер EOF був у моді, я пригадую системи захисту від копіювання, які базувалися на "копіюванні до символу EOF", що робили багато програм копіювання того часу. Деякі програми розміщують додаткові дані, які вони перевірять після маркера EOF асоційованого текстового файлу, але перед виділеним кінцем файлу. Програма копіювання не скопіювала б додаткові дані, що підтверджують чисту установку ... ах ... ностальгія.

небезпека? Як у "чи мій комп'ютер підірветься, якщо я це зроблю"? Ні.
jwenting

Відповіді:


11

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

Файлова система призначена для обробки будь-якої послідовності байтів.


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

27

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

Щоб зберегти цілісність файлу та даних, що читаються з нього, обов'язково дотримуйтесь цих вказівок:

  • Завжди відкривайте файл (читання чи запис), використовуючи один і той же режим: текстовий або двійковий. Основна відмінність полягає в тому, що текстовий режим піклується про нові рядки, і він може "відрізати" символи нових рядків під час читання файлу (залежно від конкретної бібліотеки, що використовується). Текстовий режим може також виконувати переклади Unicode, які, ймовірно, задушать дані, що не стосуються Unicode.
  • Читаючи не струнні дані, обов’язково читайте, використовуючи той самий тип даних, що і ви. Наприклад, якщо перші чотири байти файлу є описовим цілим числом, не забудьте прочитати та записати, використовуючи метод, який приймає / надає ціле число, щоб забезпечити його послідовне оброблення. Один і той же тип даних може мати різний розмір на різних машинах, і змішування типів даних на одній машині також може змінити значення даних (наприклад, інтерпретація біта в середині більшого цілого числа як біт знаків).
  • Ендіанс: якщо бібліотека, яку ви використовуєте, не обробляє це послідовно, можливо, вам доведеться обробляти її самостійно. Наприклад, Java завжди використовує мережевий порядок байтів (великий ендіан) для багатобайтових типів. C і C ++ використовують те, що вирішив виконавець бібліотеки, як правило, те саме, що і процесор (маленький ендіан для Intel, великий ендіан для більшості інших). Якщо це швидка вправа в одній системі, це не так важливо, але все-таки корисна звичка звертати на це увагу і при необхідності кодувати її.

Конкретні деталі залежать від основи, платформи та мови, але це повинно охоплювати основні "gotchas" з файлом I / O.


3
Додатковий пункт для не рядкових даних: переконайтеся, що ви використовуєте послідовну кількість байтів для кожного типу. У C і C ++ an intможе бути десь від 2 до 8 або більше байт (дійсно октетів).
Барт ван Інген Шенау

Це неявно входить до мого другого пункту, наприклад, 32 v. 64 бітове ціле число. Вони будуть різними типами даних.

Ви можете зробити це явним. Не очевидно, що intна двох різних машинах можуть розглядатися різні типи даних.
Барт ван Інген Шенау

9

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

Хороші заголовки файлів містять щонайменше три речі:

  • " Чарівне число ", принаймні чотири байти. Магічне число ОБОВ'ЯЗКОВО rfc2119 - це найперші N байтів у файлі, НІКОЛИ не повинні використовуватися для будь-якого іншого файлового формату, який ви можете викопати, і ОБОВ'ЯЗКОВО містити принаймні один байт, який не може бути надрукований символом ASCII. Дивіться специфікацію PNG, як створити дійсно ретельне магічне число. Перегляньте вихідний код file(1)команди для бази даних про існуючі магічні числа, які є настільки вичерпними, як ви, ймовірно, знайдете.

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

  • Вказівка версії формату файлу. Навіть якщо ви думаєте, що вам ніколи не доведеться різко переглянути формат вашого файлу, зробіть наступні два байти після магічного числа 00 00та задокументуйте, що це 16-бітний номер версії з певною небезпекою (що завгодно, але виберіть один і дотримуватися його у всьому файлі ) і збільшуватиметься, якщо значення наступних даних кардинально зміниться. Ваше майбутнє «я вам вдячне».

    (Специфікація PNG займає інший шлях тут, вказуючи, що формати блоку заморожені, і що всі майбутні зміни формату прийматимуть форму нових типів блоку. Це також справедливо, але я рекомендую простий магічний номер + підхід до номера версії для новачки, які розробляли PNG, спиралися на колективний десятирічний досвід роботи з форматами зображень.)

  • Якийсь механізм вбудовування довільних метаданих у файл. Це може бути так само просто, як наступні два байти - це 16-бітове зміщення від кінця заголовка до початку фактичних даних, причому все між ними слід інтерпретувати як пари клавіш-значення UTF-8 a la RFC 822 (тобто " Tag: value\n" - якщо ви йдете цим маршрутом, рекомендую не допускати складання довгих рядків). Знову ж таки, PNG значно розумніший.


Не потрібно складати власний формат файлу ... просто зберігайте дані як зображення. Вам може знадобитися змінити розмірність (наприклад, 10k x 1k), щоб вона була підтримана. Або ви можете використовувати FITS . Якщо ваші дані складніші, ніж лише один масив, ви можете використовувати HDF , CDF або NetCDF .
Джо

Я б запропонував зробити це просто. 256 різних версій буде достатньо, а якщо ні, то додаткові версії можуть бути розроблені як підривні версії 255. Так само як і для метаданих, достатньо додати їх у версію, коли вони фактично потрібні. @Joe Image ??? Ви уникаєте потенційної плутанини формату, попередньо плутаючи всіх!
maaartinus

@maaartinus Здійснення поля версії двома байтами змушує дизайнера формату брати участь у випереджанні. Простір для метаданих завжди має бути у версії 0 двійкового формату, інакше ви закінчитеся жахливими помилками, такими як ID3. Я дуже симпатизую логіці специфікації PNG щодо розширюваності через нові типи фрагментів замість ударів у форматі версії. Однак файли, структуровані фрагментами, створюють купу власних складностей, тому я не вагаюся рекомендувати їх для простих випадків. Я був спокуса рекомендувати HDF як загальний формат , який займався з великою кількістю вже цих питань.
zwol

2

Різні архітектури мають різні подання для цілих чисел. Основний ризик тут - збереження байтового представлення цілого числа в машині A, а потім спроба прочитати це назад і інтерпретувати вміст як цілі числа в машині B. Якщо машини A і B мають різні розміри для цілих чисел та / або різної витривалості , ви ' найімовірніше, це спричинить невизначену поведінку (наприклад, в С) або виняток.

Оскільки це лише приклад програмування, а не «реальна» програма, це насправді не проблема. Якщо це була реальна програма, прокатування власного двійкового формату, що відповідає додатку, зазвичай не є хорошою ідеєю; є кращі рішення, як-от формати серіалізації на основі SQLite або рядки, такі як JSON, YAML, XML тощо. Для одиничних значень достатньо перетворення їх у рядок; для простих списків ви можете зберегти по одному рядку на рядок і просто розділити введення на нові рядки, коли ви прочитаєте його ще раз.


Погодьтесь загалом, але JSON або XML значно збільшили розмір файлу, що містить 10 ^ 7 чисел. Крім того, вони, як правило, читають і розбирають все відразу, але розглянутий розділ стосується сортування файлів, що містять більше даних, ніж ви можете вмістити у наявну пам'ять.
Калеб

Це залежить від того, що ти робиш. Іноді хіт продуктивності SQL проти власної ролі є головним. Востаннє, коли я це робив, у мене були невеликі записи, і був великий шанс, що мені захочеться сусідів. Читання більшого блоку з диска зазвичай не коштувало майже нічого, тому якби я хотів одного запису, я прочитав 1000 у кеш. Мої записи майже напевно були поруч, при цьому SQL голова диска підскакувала всюди.
Лорен Печтел
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.