外部組爲我提供了一個寫在Big Endian機器上的文件,並且它們還爲文件格式提供了C++解析器。用小端程序讀取大端數據的任何方法?
我只能一點點端機器上運行的解析器 - 有沒有辦法用自己的解析器,而不讀取該文件在每次讀添加swapbytes()調用?
外部組爲我提供了一個寫在Big Endian機器上的文件,並且它們還爲文件格式提供了C++解析器。用小端程序讀取大端數據的任何方法?
我只能一點點端機器上運行的解析器 - 有沒有辦法用自己的解析器,而不讀取該文件在每次讀添加swapbytes()調用?
早在鐵器時代,古人遇到過這個問題,當他們試圖向網絡原始PDP-11小型機與其他原始計算機。 PDP-11是第一臺Little-Endian計算機,而當時大多數其他計算機都是big-Endian。爲了解決這個問題,他們一勞永逸地開發了網絡字節順序概念(總是big-Endia)和相應的網絡字節順序宏ntohs(),ntohl(),htons()和htonl() )。用這些宏編寫的代碼將永遠「得到正確答案」。
你的外部供應商使用的宏在他們的代碼,他們提供你將永遠是大端文件精益,即使切換到little-endian的機器。重寫他們給你的解析器來使用宏,即使你切換到big-endian機器,你也將永遠可以讀取他們的文件。
在這個特殊問題上浪費了大量的程序員時間。有幾天我認爲可以懸掛PDP-11設計師做出小端特徵決定的一個很好的論點。
一般來說,沒有「簡單」的解決方案。您將不得不修改解析器以交換從文件中讀取的每個整數的字節。
這取決於你在處理數據。如果打算將數據打印出來,則需要交換所有數字上的字節。如果您通過文件查看一個或多個值,則字節交換比較值可能會更快。
一般來說,格雷格是正確的,你必須努力去做。
「如果你正在通過文件查看一個或多個值......」意思是基本上你會寫你自己的解析器。你不能使用沒有先交換文件內容的解析器,因爲你不知道它是否依賴於機器的永久性。 – groovingandi
不知道提供的解析器的API的一些細節,也不知道解析數據的預期用途,我提供的優化可能會適得其反。 –
你可以寫一個包裝自己的解析器和反轉的字節數,如果你不希望修改自己的解析器解析器。
請注意讀取數據的類型。4字節的int
或float
需要endian校正。一個4字節的ASCII字符串不會。
甚至可能無法打包它們的解析器 - 如果它檢查幻數,那麼當它們加載錯端時,它將無法找到它們。存儲在數據中的大小也會被誤讀。 –
一般來說,沒有。
如果讀/寫呼叫不知道類型(其中,例如FREAD和fwrite沒有),那麼他們不能告訴書寫端敏感數據和尾數敏感數據之間的差異。
根據解析器結構的不同,如果它們使用的I/O函數知道正在讀取/寫入的類型,那麼您可能可以避免一些痛苦,那麼您可以修改那些例程以應用正確的endian轉換。
如果您還需要修改所有的讀/寫調用,那麼建立這樣一個程序將是一個明智的行動過程。
最好的方法是隻定義文件格式的字節數,而不是說它是與機器相關的。 作者將不得不按照正確的順序寫入字節,而不管它運行在哪個CPU上,讀者也必須這樣做。
嘗試說服解析器團隊,包括下面的代碼:
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));
消費,但總是會得到存儲方式對上既大又小尾數系統。
你的字節怎麼只有4位? ;-) –
,因爲那是在你半睡着時編寫代碼時發生的情況 – doron
你的問題以某種方式conatins答案:不!
我只能一點點端機器上運行的解析器 - 有沒有辦法用自己的解析器不讀取文件添加swapbytes()後,每次讀打電話?
如果你讀(並想解釋)小端機器上大端數據,你必須莫名其妙某處和轉換數據。您可能會在每次讀取後或整個文件讀取後執行此操作(如果讀取的數據不包含有關如何讀取更多數據的任何信息) - 但無法省略轉換。
我會獾外部組支持便攜式格式,如XML。 – 2010-01-07 18:12:36
或者至少提供一個沒有損壞的解析器。如果他們的解析器只能在big-endian機器上工作,那麼他們的解析器就會被破壞。讓他們修正它(或接受修補作爲貢獻)可能更爲現實,而不是篡改它們來改變它們的文件格式。 –
編譯一個big-endian機器的代碼並在你的little-endian機器上的'qemu'下運行它:D – ephemient