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

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

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


person Brian    schedule 07.01.2010    source источник
comment
Я бы уговорил внешнюю группу поддерживать переносимый формат, такой как XML.   -  person    schedule 07.01.2010
comment
Или, по крайней мере, предоставить парсер, который не сломан. Если их синтаксический анализатор работает только на машинах с обратным порядком байтов, то их синтаксический анализатор неисправен. Возможно, было бы более реалистично уговорить их исправить это (или принять исправление в качестве вклада), чем уговаривать их изменить формат файла.   -  person Steve Jessop    schedule 07.01.2010
comment
Скомпилируйте код для машины с прямым порядком байтов и запустите его под qemu на своей машине с прямым порядком байтов :D   -  person ephemient    schedule 07.01.2010


Ответы (8)


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

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

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

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

person John R. Strohm    schedule 07.01.2010

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

person Greg Hewgill    schedule 07.01.2010

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

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

person Thomas Jones-Low    schedule 07.01.2010
comment
Если вы ищете в файле одно или несколько значений... в основном это означает, что вы напишете свой собственный синтаксический анализатор. Вы не можете использовать предоставленный синтаксический анализатор без предварительной замены содержимого файла, поскольку вы не знаете, полагается ли он на порядок байтов машины. - person groovingandi; 07.01.2010
comment
Не зная некоторых подробностей об API для предоставленного синтаксического анализатора или предполагаемого использования в качестве проанализированных данных, оптимизация, которую я предоставил, вполне может быть контрпродуктивной. - person Thomas Jones-Low; 07.01.2010

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

person Omry Yadan    schedule 07.01.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));, но всегда будет правильно выполнять порядок байтов как в системах с большим, так и с маленьким порядком байтов.

person doron    schedule 07.01.2010
comment
Почему в ваших байтах всего 4 бита? ;-) - person Steve Jessop; 07.01.2010
comment
потому что это то, что происходит, когда вы пишете код, когда вы в полусне - person doron; 08.01.2010

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

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

person Drew Dormann    schedule 07.01.2010
comment
Может быть даже невозможно обернуть их парсер - если он проверяет магические числа, то не сможет их найти, когда они загружены с неправильным порядком байтов. Размеры, хранящиеся в данных, также будут неправильно считаны. - person Steve Jessop; 07.01.2010

В общем, нет.

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

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

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

person Adam Bowen    schedule 07.01.2010

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

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

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

person RED SOFT ADAIR    schedule 07.01.2010