簡體   English   中英

如何使用指針數組(解析二進制文件)反轉數據

[英]How to reverse data using an array of pointers (parse binary file)

我正在使用規范解析二進制文件。 該文件采用大端模式,因為它已累積了流式傳輸的數據包。 我必須反轉數據包的長度,以便將它們“ reinterpret_cast”轉換為正確的變量類型。 (由於數據包的長度不同,我無法使用net / inet.h函數)。

ifstream類的read()方法將字節放入圖表指針數組中。 我嘗試使用a進行手動還原,但無法弄清楚如何通過“指針列表”來更改它們在數組中的位置。

如果有人知道更有效的方法,請告訴我(需要解析8gb的數據)。

#include <iostream>
#include <fstream>

void reverse(char &array[]);

using namespace std;

int main ()
{
    char *a[5];
    *a[0]='a'; *a[1]='b'; *a[2]='c'; *a[3]='d'; *a[4]='e';

    reverse(a);

    int i=0;
    while(i<=4)
    {
        cout << *a[i] << endl;
        i++;
    }
    return 0;
}
void reverse(char &array[])
{
    int size = sizeof(array[])+1;
    //int size = 5;
    cout << "ARRAY SIZE: " << size << endl;

    char aux;
    for (int i=0;i<size/2;i++)
    {
            aux=array[i];
            array[i]=array[size-i-1];
            array[size-i-1]=aux;
    }
}

謝謝大家的幫助!

不完全的。

該文件采用大端模式,因為它已累積了流式傳輸的數據包。 我必須反轉數據包的長度,以便將它們“ reinterpret_cast”轉換為正確的變量類型。

您需要反轉存儲數據級別的字節,而不是文件而不是數據包。

例如,如果文件存儲結構。

struct S {
  int i;
  double d;
  char c;
};

閱讀該結構,您將需要反轉:

int: [4321]->[1234]  // sizeof(int) == 4, swap the order of 4 bytes
double: [87654321]->[12345678]  // sizeof(double) == 8, swap the order of 8 bytes
char: [1]->[1]  // sizeof(char) == 1, swap 1 byte (no swapping needed)

並非一次完成整個結構。

不幸的是,它並沒有像反轉文件中的數據塊或文件本身那樣簡單。 您需要確切地知道要存儲什么數據類型,並反轉其中的字節。

inet.h中的函數正是用於此目的,因此,我建議您使用它們。

因此,這使我們進入了c字符串。 如果要將c字符串存儲在文件中,是否需要交換它們的字節序? 嗯,ac字符串是一個1字節char s的序列。 您不需要交換1個字節的char ,因此您不需要交換ac字符串中的數據!

如果您確實想交換6個字節,則可以使用std::reverse函數:

char in[6] = get6bytes();
cout << in << endl;  // shows abcdef 
std::reverse(in, in+6);
cout << in << endl;  // shows fedcba

如果您要進行任何大規模(大量類型)的操作,那么您可能要考慮編寫一個代碼生成器來生成這些字節交換功能(和文件讀取功能),只要您願意,它就不會太難可以找到一種工具來解析c中的結構(為此我使用了gcc-xml ,也許clang會有所幫助)。

這使得序列化成為一個更困難的問題。 如果力所能及,您可能要考慮使用XML或Google的協議緩沖區為您解決這些問題。

好的,發表您的評論后,我了解您的要求。 因此,您需要更改6字節寬的字段的字節序。

我認為這篇文章以及關於SO的問題都應該為您提供幫助,它展示了如何以不同的方式實現轉換,最快的是按位實現。 它沒有顯示六字節寬字段的實現,但是可以輕松地做出類似的解決方案。

我建議以64位整數復制您的length字段,然后實現自定義函數以交換相關的6個字節。 在任何情況下都擺脫掉或所有char指針...;)

如果您使用VC ++進行編譯,則具有以下功能: _byteswap_uint64 在此uint64的高端中超過6個字節,調用此函數並執行Hopla,就完成了。

在凌晨4:12進行編輯 (我一定非常沉迷於stackoverflow)

#include <iostream>
#include <stdlib.h>

typedef unsigned char    byte;
typedef unsigned __int64 uint64_t; // uncomment if you are not on VC++

// in case you are not compiling with VC++ use this custom function
// It can swap data of any size. Adapted from:
// https://stackoverflow.com/questions/2182002/convert-big-endian-to-little-endian-in-c-without-using-provided-func/2182581#2182581
// see: http://en.wikipedia.org/wiki/XOR_swap_algorithm

void
swapBytes( void* v, size_t n )
{
   byte* in = (byte*) v;

   for( size_t lo=0, hi=n-1; hi>lo; ++lo, --hi )

      in[lo] ^= in[hi]
   ,  in[hi] ^= in[lo]
   ,  in[lo] ^= in[hi] ;
}

#define SWAP(x) swapBytes( &x, sizeof(x) );


int
main()
{
   // pointer to location of length field. 
   // You will have to read it from file to memory.
   byte length[6] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };

   // ok, you have read it from file, now get it in an uint64_t
   uint64_t i = *( (uint64_t*)  length );

   i <<= 16; // zero two bytes and move everything to the high end.

   std::cout << std::hex << i                     << std::endl;
   std::cout << std::hex << _byteswap_uint64( i ) << std::endl;

   // generic swapping function
   SWAP( i ) 
   std::cout << std::hex << i                     << std::endl;

   std::cin.get();
   return 0;
}

// Outputs:
// 605040302010000
// 10203040506
// 10203040506

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM