我正在使用规范解析二进制文件。该文件以big-endian模式进行,因为它已经累积了流式传输数据包。我必须反转数据包的长度,以便将它们“重新解释”为正确的变量类型。 (我无法使用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;
}
}
感谢各位的帮助!
答案 0 :(得分:2)
不完全。
该文件采用big-endian模式,因为它已经累积了流式传输数据包。我必须反转数据包的长度,以便将它们“重新解释”为正确的变量类型。
您需要反转存储数据级别的字节,而不是文件而不是数据包。
例如,如果文件存储结构。
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字符串存储在文件中,是否需要交换其字节序?好吧,c字符串是1字节char
s的序列。您不需要交换1个字节char
,因此您不需要交换c字符串中的数据!
如果您真的想要交换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的协议缓冲来为您解决这些问题。
答案 1 :(得分:0)
好的,在您发表评论后,我明白您的意思。因此,您需要更改6字节宽的字段的字节顺序。
我认为this article应该对您和this question on SO有所帮助,它展示了如何以不同的方式实现转换,最快的是按位实现。它没有显示六字节宽字段的实现,但可以轻松地制作类似的解决方案。
我建议在64位整数中复制长度字段,然后实现自定义函数来交换相关的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