Есть ли способ прочитать данные с прямым порядком байтов с помощью программы с прямым порядком байтов? - PullRequest
4 голосов
/ 07 января 2010

Внешняя группа предоставляет мне файл, написанный на машине с Big Endian, и они также предоставляют синтаксический анализатор C ++ для формата файла.

Я могу запустить парсер только на машине с прямым порядком байтов - есть ли способ прочитать файл, используя их парсер, без добавления вызова swapbytes () после каждого чтения?

Ответы [ 8 ]

13 голосов
/ 07 января 2010

Еще в раннем железном веке древние столкнулись с этой проблемой, когда пытались объединить примитивные миникомпьютеры PDP-11 с другими примитивными компьютерами. PDP-11 был первым компьютером с прямым порядком байтов, в то время как большинство других в то время были с прямым порядком байтов.

Чтобы решить эту проблему, они раз и навсегда разработали концепцию сетевого порядка байтов (всегда big-Endia) и соответствующие макросы сетевого порядка байтов ntohs (), ntohl (), htons () и htonl (). , Код, написанный с этими макросами, всегда будет "давать правильный ответ".

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

На эту конкретную проблему было потрачено действительно огромное количество времени программиста. Бывают дни, когда я думаю, что можно привести веские аргументы в пользу того, чтобы повесить дизайнера PDP-11, который принял решение о функции с прямым порядком байтов.

2 голосов
/ 07 января 2010

Попробуйте убедить команду парсера включить следующий код:

int getInt(char* bytes, int num)
{
    int ret;
    assert(num == 4);
    ret = bytes[0] << 24;
    ret |= bytes[1] << 16;
    ret |= bytes[2] << 8;
    ret |= bytes[3];
    return ret;
}

это может занять больше времени, чем обычный int i = *(reinterpret_cast<*int>(&myCharArray));, но всегда будет иметь правильный порядок байтов как в больших, так и в маленьких системах.

2 голосов
/ 07 января 2010

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

2 голосов
/ 07 января 2010

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

В общем, Грег прав, тебе придется сделать это нелегко.

2 голосов
/ 07 января 2010

В общем, для этого нет «простого» решения.Вам нужно будет изменить синтаксический анализатор, чтобы поменять местами байты каждого целого числа, считанного из файла.

0 голосов
/ 08 января 2010

Ваш вопрос как-то содержит ответ: Нет!

Я могу запустить парсер только на машине с прямым порядком байтов - есть ли способ прочитать файл, используя их парсер, без добавления вызова swapbytes () после каждого чтения?

Если вы читаете (и хотите интерпретировать) данные с прямым порядком байтов на машине с прямым порядком байтов, вы должны каким-то образом и где-то конвертировать данные. Вы можете сделать это после каждого чтения или после прочтения всего файла (если прочитанные данные не содержат никакой информации о том, как читать дополнительные данные), - но невозможно пропустить преобразование.

0 голосов
/ 07 января 2010

В общем, нет.

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

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

Если вам нужно изменить все вызовы чтения / записи, то создание именно такой подпрограммы было бы разумным шагом.

0 голосов
/ 07 января 2010

Вы можете написать синтаксический анализатор, который оборачивает их синтаксический анализатор и инвертирует байты, если вы не хотите изменять их синтаксический анализатор.

Помните о типах считываемых данных. 4-байтовый int или float потребует коррекции порядка байтов. 4-байтовая строка ASCII не будет.

...