В двоичном файле поменять местами две записи с заданными числами

Обновлено: 02.07.2024

Чтение двоичных данных или запись двоичных данных в соединение или необработанный вектор.

Использование

Аргументы

Объект соединения или строка символов, обозначающая файл или необработанный вектор.

Либо объект, режим которого задает режим считываемого вектора, либо вектор символов длины один, описывающий режим: один из «числовых», «двойных», «целых», «целых», «логических». " , "сложный", "символ", "сырой" .

числовой. (Максимальное) количество записей для чтения. Здесь вы можете использовать завышенную оценку, но не слишком большую, так как хранилище зарезервировано для n элементов.

целое число. Количество байтов на элемент в потоке байтов. По умолчанию NA_integer_ использует натуральный размер. Изменение размера не поддерживается для необработанных и сложных векторов.

логично. Используется только для целых чисел размеров 1 и 2, когда определяет, следует ли рассматривать количество в файле как целое число со знаком или без знака.

Последовательность байтов («большой» или «маленький») целевой системы для файла. Использование "swap" приведет к замене порядка следования байтов.

Объект R для записи в соединение.

Подробнее

Эти функции можно использовать только с подключениями в двоичном режиме. Если con представляет собой строку символов, функции вызывают файл для получения подключения к файлу в двоичном режиме, которое открывается на время вызова функции.

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

Если readBin вызывается с con необработанным вектором, данные в векторе используются в качестве входных данных. Если writeBin вызывается с con необработанным вектором, это просто указывает на то, что необработанный вектор должен быть возвращен.

Если указан размер, а не естественный размер объекта, каждый элемент вектора приводится к соответствующему типу перед записью или чтением. Возможные размеры: 1, 2, 4 и, возможно, 8 для целочисленных или логических векторов и 4, 8 и, возможно, 12/16 для числовых векторов. (Обратите внимание, что приведение происходит для типов со знаком, за исключением случая, когда signed = FALSE при чтении целых чисел размеров 1 и 2.) Изменение размеров вряд ли сохранит NA, а размеры повышенной точности вряд ли будут переносимы между платформами.

readBin и writeBin читают и записывают строки символов в стиле C, заканчивающиеся нулем. Длина входных строк ограничена 10000 символов. readChar и writeChar можно использовать для чтения и записи строк фиксированной длины. Проверка правильности строки в кодировке текущей локали не выполняется.

Обработка отсутствующих и специальных значений R ( Inf , -Inf и NaN ) обсуждается в руководстве «Импорт/экспорт данных R».

За один вызов можно записать только 2^31 - 1 байт (и это максимальная емкость необработанного вектора на 32-разрядных платформах).

«Endian-ness» актуален для размера > 1 и всегда должен устанавливаться для переносимого кода (значение по умолчанию подходит только при записи и последующем чтении файлов на одной и той же платформе).

Значение

Для readBin – вектор соответствующего режима и длины, равный количеству прочитанных элементов (которое может быть меньше n).

Для writeBin необработанный вектор (если con является необработанным вектором) или невидимый NULL .

Чтение/запись целых чисел размера 8 будет доступно, если либо тип C long имеет размер 8 байт, либо тип C long long существует и имеет размер 8 байтов.

Реальные операции чтения/записи размера sizeof(long double) (обычно 12 или 16 байт) будут доступны, только если этот тип доступен и отличается от double .

Если readBin(what = character()) неправильно используется в файле, который не содержит строк символов в стиле C, выдаются предупреждения (обычно много). Входные данные из файла или подключения будут разбиты на части длиной 10 000, а любая последняя часть будет отброшена.

Понимание природы форматов файлов и управляющих символов было моей головной болью. Недавно я нашел несколько полезных объяснений, которые вдохновили меня написать свое понимание двоичных файлов.

Как компьютеры представляют данные

Все состоит из битов и байтов, единиц и нулей для компьютера. Люди понимают текст, поэтому у нас есть программы, которые преобразуют последовательность единиц и нулей во что-то, что мы можем понять.

В символьной схеме ASCII один байт (последовательность из восьми единиц или нулей или число от 0 до 255) может быть преобразован в символ. Например, символ «А» — это число 65 в десятичном формате, 41 в шестнадцатеричном формате или 01000001 в двоичном формате. «B» — это десятичное число 66 и т. д. (см. полную таблицу).

Не верите мне? Мини-пример времени.

Создайте в блокноте файл с одной буквой «А» (подойдет любое имя файла — «sample.txt»).

Сохраните файл, щелкните правой кнопкой мыши и посмотрите свойства — он должен быть 1 байт: блокнот хранит символы в ASCII, по одному байту на символ.«Размер на диске» может быть больше, поскольку компьютер выделяет место фиксированными блоками (например, по 4 килобайта).

notepad_A.jpg

notepad_A_size.jpg< бр />

Найдите шестнадцатеричный редактор (вот бесплатный) и откройте только что сохраненный файл. (В Linux/Unix используйте «od -x sample.txt»).

Вы увидите только одно число "41" в шестнадцатеричном формате (65 в десятичном), а шестнадцатеричный редактор может отображать символ "A" на боковом экране (представление байта, который вы проверяете, в ASCII). «0» слева — это адрес байта — программисты любят считать с нуля.

notepad_A_hexedit.PNG

Круто, да? Эти заголовки или «магические числа» — один из способов для программы определить, какой тип файла она видит. Если вы откроете изображение PNG, вы увидите заголовок PNG, который включает буквы ASCII «PNG».

Что происходит?

В памяти компьютера в файле sample.txt хранится только число 65 (41 в шестнадцатеричном формате или 01000001 в двоичном формате). Учитывая контекст информации (например, блокнот ожидает текстовый файл), компьютер знает, что нужно отобразить на экране символ ASCII «A».

Теперь подумайте, как человек запомнит фактическое числовое значение 65, если вы попросите его записать его. Как люди, мы бы написали это как два символа: «6» и затем «5», что занимает 2 символа ASCII или 2 байта (опять же, «буква» 6 может быть сохранена в ASCII).

Компьютер сохранит число "65" как 65 в двоичном формате, как и "а". За исключением этого случая, программное обеспечение будет знать, что «65» — это не код буквы, а сама цифра.

Теперь предположим, что мы хотим сохранить число 4 000 000 000 (4 миллиарда). Как люди, мы бы написали это как 4000000000 или 10 символов ASCII (10 байт). Как это сделает компьютер?

Один байт имеет 8 бит или 2^8 (256) возможных значений. 4 байта дают нам 2^32 бита или примерно 4 миллиарда значений. Таким образом, мы смогли сохранить число 4 миллиарда всего в 4 байтах.

Как видите, хранение числовых данных в формате компьютера позволяет сэкономить место. Это также экономит вычислительные ресурсы — компьютеру не нужно преобразовывать число между двоичным кодом и кодом ASCII.

Итак, почему бы не использовать двоичные форматы?

Если двоичные форматы более эффективны, почему бы не использовать их постоянно?

  • Двоичные файлы трудно читать людям. Когда человек видит последовательность из 4 байтов, он понятия не имеет, что она означает (это может быть 4-буквенное слово, хранящееся в ASCII). Если он увидит 10 букв ASCII 4000000000, он узнает, что это число.
  • Двоичные файлы трудно редактировать. Точно так же, если человек хочет изменить 4 миллиарда на 2 миллиарда, ему нужно знать двоичное представление. В представлении ASCII он может просто поставить «2» вместо «4».
  • С двоичными файлами сложно работать. Традиция UNIX включает в себя несколько простых и элегантных инструментов для работы с текстом. Сохраняя файлы в стандартном текстовом формате, вы получаете всю мощь этих инструментов без необходимости создавать специальные редакторы для изменения двоичного файла.
  • Двоичные файлы могут сбивать с толку. Проблемы возникают, когда компьютеры используют разные способы чтения данных. Существует нечто, называемое «NUXI» или проблема с порядком байтов, которая возникает, когда 2 компьютера с разными архитектурами (например, PowerPC Mac и x86 PC) пытаются передать двоичные данные. Обычный текст, хранящийся в одиночных байтах, однозначен, но будьте осторожны с Юникодом.
  • Прирост эффективности обычно невелик. Представление чисел в двоичном виде может в идеале сэкономить вам коэффициент 3 (4-байтовое число может представлять 10 байтов текста). Однако это предполагает, что числа, которые вы представляете, большие (3-значное число, такое как 999, лучше представлено в ASCII, чем в виде 4-байтового числа). Наконец, ASCII на самом деле использует только 7 бит на байт, поэтому вы теоретически упаковываете ASCII вместе, чтобы получить выигрыш в 1/8 или 12%. Однако хранить текст таким образом обычно не стоит хлопот.

Одна из причин эффективности двоичных файлов заключается в том, что они могут использовать все 8 битов в байте, в то время как большая часть текста ограничена определенными фиксированными шаблонами, оставляя неиспользуемое пространство. Однако, сжимая текстовые данные, вы можете уменьшить объем используемого пространства и сделать текст более эффективным.

Упорядочивание и рассортировка данных

Кроме того, Маршаллинг всегда заставляет меня думать о шерифах Маршалах и, следовательно, о ковбоях. Ковбои не имеют ничего общего со значением слова «маршал» в CS.

Иногда компьютеры имеют сложные внутренние структуры данных с цепочками связанных элементов, которые необходимо хранить в файле. Маршаллинг – это процесс извлечения внутренних данных программы и их сохранения в плоский линейный файл. Разупорядочение — это процесс чтения этих линейных данных и воссоздания сложной внутренней структуры данных, которая изначально была в компьютере.

С Блокнотом все просто: ему просто нужно сохранить необработанный текст, поэтому упорядочение не требуется. Microsoft Word, однако, должен хранить текст вместе с другой информацией о документе (поля страницы, размеры шрифта, встроенные изображения, стили и т. д.) в одном линейном файле. Позже он должен прочитать этот файл и воссоздать исходную настройку пользователя.

Вы можете маршалировать данные в двоичном или текстовом формате — слово «маршалировать» не указывает, как данные хранятся.

Так когда же полезны двоичные форматы файлов?

В некоторых ситуациях может потребоваться использование двоичных форматов файлов. Изображения PNG используют двоичный формат, поскольку при создании небольших файлов изображений важна эффективность. Однако PNG правильно работает с двоичными форматами: он определяет порядок байтов и длину слова, чтобы избежать проблемы NUXI.

Часто использование двоичных форматов связано с бизнесом. Основная причина в том, что их труднее реконструировать (людям приходится догадываться, как компьютер хранит свои данные), что может помочь сохранить конкурентное преимущество.

Другие сообщения из этой серии

Присоединяйтесь к 450 тысячам читателей в месяц

Понравилась статья? Есть много других вещей, которые помогут вам построить прочное интуитивное понимание математики. Подпишитесь на информационный бюллетень, чтобы получать бонусный контент и последние обновления.

 Петр

Насколько я знаю, fread не решит эту проблему (легко), поскольку применяет однократное переназначение ко всему файлу. У меня есть двоичный файл с полями разной длины и типа в байтах (2- и 4-байтовые целые числа, а также числа с плавающей запятой), которые необходимо поменять местами.

Моя единственная идея сейчас — использовать fread и устанавливать позицию каждой записи (break для изменения типа перестановки байтов). Хотя это может работать, это не очень желательно для проекта из-за длины каждого файла данных и количества идентификаторов файлов, которые будут плавать вокруг, плюс их нужно будет создавать динамически в зависимости от объема данных, записанных в данный мультиплексированный файл. файл. Проект пытается получить данные SEGY из пользовательской структуры мультиплексирования, написанной почтовым документом, который, вероятно, уже устарел, и никто не может найти описание структуры мультиплексирования. Я лучше всего знаком с MatLab (почему я пытаюсь сделать это здесь), но хотел бы получить конечный сценарий на C. Альтернативой является создание сценариев Unix через какой-то пакет. Я не нашел хорошего пакета, чтобы сделать что-то подобное, поэтому, если вы знаете что-то по этому пути, я внимательно слушаю.

1 комментарий

 Джефф

Прямая ссылка на этот комментарий

Прямая ссылка на этот комментарий

Да, я бы сделал это на C. Но вы можете сделать это и в MatLab, если хотите. Просто прочитайте весь файл как двоичный и выполните соответствующий массаж. Когда вы говорите «перестановка байтов», я предполагаю, что вы имеете в виду изменение «порядка байтов».

Лучший способ сделать вывод о структуре двоичного формата файла — изучить его в шестнадцатеричном редакторе. Должен быть хороший бесплатный шестнадцатеричный редактор для Mac на расстоянии одного Google.

Ответы (2)

 Джефф

Прямая ссылка на этот ответ

Прямая ссылка на этот ответ

Привет, Питер, ты действительно знаешь формат своих данных? У меня сложилось впечатление, что вы не знаете, что такое бинарная структура. Послушайте, если это так, то это должно быть проще, чем вы думаете.

Теперь, если у вас есть определенная структура, которая повторяется в файле, сделайте сопоставление того, как следует изменять байты в этой структуре:

Затем переупорядочите байты данных, чтобы привести их в соответствие с этой структурой (при условии, что ее размер кратен размеру этой структуры) -- каждый столбец будет представлять один экземпляр структуры:

3 комментария

Джефф

Прямая ссылка на этот комментарий

Прямая ссылка на этот комментарий

 Петр

Прямая ссылка на этот комментарий

Прямая ссылка на этот комментарий

Джефф, вау! Этот метод действительно поможет, и спасибо за щедрое предложение. Это заводит меня очень далеко, но есть еще кое-что, что нужно сделать, и я думаю, что фильтр соответствия sudo сработает. Файл данных состоит из:

Формат мультиплексного заголовка неизвестен, как и любой штамп EoF. Если у «канала» есть данные (не у всех есть, и я не знаю, что там в качестве заполнителя, если есть), это формат SEGY, где файл SEGY:

Я знаю байтовую структуру файла SEGY и заголовки трассировки, а также количество выборок на набор данных (из некоторых нацарапанных заметок на магнитной ленте, реальных . Поэтому я думаю, что могу создать байтовую карту (как вы назвали ее выше). ) заголовков трассировки, два пробела из них — число выборок и запустите его как фильтр соответствия, ища поля в заголовке трассы, которые не должны изменяться от трассы к трассе. Заголовок файла SEGY будет находиться непосредственно перед заголовок 1-й трассы, поэтому я могу взять и декодировать его, чтобы узнать, сколько трасс имеет первый файл, и продолжить просмотр остальных данных в поисках следующего файла SEGY. каналы, мне придется заняться мультиплексным заголовком, надеюсь, это все переменная одного типа, для которой я могу просто выполнять случайную замену байтов и сравнивать с размером и расположением файлов SEGY, не прибегая к шестнадцатеричному дампу.

На самом деле эта игра предназначена для получения заголовка мультиплексора, чтобы можно было написать новый код для обработки всех оставшихся файлов, в которых я не знаю количества выборок или чего-то еще, кроме мультиплексированных данных SEGY.< /p>

Ferret может читать двоичные файлы данных, отформатированные с заголовками длины записи FORTRAN или без них (двоичные файлы без форматирования длины записи FORTRAN также известны как "потоковые" файлы).

ПРИМЕЧАНИЕ. Эти типы файлов активно не поддерживаются. Возможности исторически были в Ferret/PyFerret, но более современные типы файлов поощряются из-за их независимости от машины и самодокументирования.

2.4.1 Двоичные файлы со структурой FORTRAN

Файлы, содержащие информацию о длине записи, создаются программами FORTRAN с использованием режима создания файлов ACCESS="SEQUENTIAL" (по умолчанию FORTRAN), а также программой Ferret с использованием LIST/FORMAT=unf. Файлы, содержащие заголовки длины записи FORTRAN, должны иметь все данные, выровненные по 4-байтовой границе. Предположим, что "rrrr" представляет 4 байта информации о длине записи, а "dddd" представляет 4-байтовое значение данных. Затем файлы в формате FORTRAN организуются одним из следующих двух способов:

2.4.1.1 Записи одинаковой длины

Файл со структурой FORTRAN с записями одинаковой длины (3 значения данных с плавающей запятой одинарной точности на запись на этом рисунке) выглядит следующим образом:

Код FORTRAN, который создает файл данных этого типа, может выглядеть примерно так (последовательный доступ используется по умолчанию и не требует указания в операторе OPEN):

Чтобы получить доступ к данным из этого файла, используйте

Это очень похоже на доступ к данным ASCII с добавлением квалификатора /FORMAT=unf. Квалификатор /COLUMNS= сообщает Ferret количество значений данных в записи. Несмотря на то, что в приведенном выше примере этот квалификатор является необязательным, он необходим, если количество значений данных на запись больше, чем количество считываемых переменных (примеры приведены в разделе «Данные ASCII»).

2.4.1.2 Записи разной длины

Файл в формате FORTRAN с записями переменной длины может выглядеть следующим образом:

С осторожностью можно прочитать файл данных, содержащий записи переменной длины, который был создан с использованием простейшего неформатированного оператора FORTRAN OPEN и одного оператора WRITE для каждой переменной. Используйте /FORMAT=stream для чтения таких файлов. Обратите внимание, что последовательный доступ используется в FORTRAN по умолчанию, и его не нужно указывать в операторе OPEN:

Аргумент 1003 представляет собой сумму 1000 слов данных в записи 1, плюс 2 слова информации о длине записи, окружающие значения данных в записи 1 (переменная var1), плюс 1 слово информации о записи, предшествующее данным в записи 2.

При чтении из потоковых или двоичных файлов при запросе данных считывается вся сетка. Чтобы читать подмножества данных, можно определить меньшую сетку для чтения подмножества записей и, возможно, записать его в файл netCDF, выполнить второе чтение, пропустив эти первые записи и т. д.

2.4.1.3 Бинарные файлы Fortran, переменные в разных сетках.

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

Размер файла данных (1+1+1+360*180+1)*12*4 = 3 110 592 байт. Такой файл нельзя прочитать с помощью квалификатора /FORMAT=unf, но его можно прочитать с помощью квалификатора /FORMAT=stream, описанного в следующем разделе. Включив квалификатор /SWAP, этот метод можно использовать для чтения файлов, созданных на компьютере с другим порядком байтов.

Следующие команды прочитают этот файл и назначат данные соответствующей сетке:

2.4.2 Потоковая передача двоичных файлов

Файлы без встроенной информации о длине записи создаются программами FORTRAN с использованием ACCESS="DIRECT" в операторах OPEN и программами C с использованием библиотеки C studio. Эти файлы могут содержать как целые, так и действительные числа. Следующие типы могут быть прочитаны из неструктурированного файла:

Читайте также: