[英]How to shift the bytes using Big Endian format instead of Little Endian in C++?
I am writing Byte Array value into a file using Java with Big Endian Byte Order format.. Now I need to read that file from C++ program... 我正在使用Big Endian字节顺序格式的Java将字节数组值写入文件。现在,我需要从C ++程序读取该文件...
That Byte Array which I am writing into a file is made up of three Byte Arrays as described below- 我要写入文件的字节数组由三个字节数组组成,如下所述-
short employeeId = 32767;
long lastModifiedDate = "1379811105109L";
byte[] attributeValue = os.toByteArray();
I am writing employeeId
, lastModifiedDate
and attributeValue
together into a single Byte Array and that resulting Byte Array I am writing into a file and then I will be having my C++ program which will retrieve that Byte Array data from file and then deserialize it to extract employeeId
, lastModifiedDate
and attributeValue
from it. 我正在将
employeeId
, lastModifiedDate
和attributeValue
一起写入一个字节数组,并将所得的字节数组写入文件中,然后将使用C ++程序,该程序将从文件中检索该字节数组数据,然后反序列化以提取employeeId
, lastModifiedDate
和attributeValue
。
Below is my working Java code, which writes Byte Array value into a file with Big Endian format: 以下是我的工作Java代码,该代码将字节数组值写入Big Endian格式的文件中:
public class ByteBufferTest {
public static void main(String[] args) {
String text = "Byte Array Test For Big Endian";
byte[] attributeValue = text.getBytes();
long lastModifiedDate = 1289811105109L;
short employeeId = 32767;
int size = 2 + 8 + 4 + attributeValue.length; // short is 2 bytes, long 8 and int 4
ByteBuffer bbuf = ByteBuffer.allocate(size);
bbuf.order(ByteOrder.BIG_ENDIAN);
bbuf.putShort(employeeId);
bbuf.putLong(lastModifiedDate);
bbuf.putInt(attributeValue.length);
bbuf.put(attributeValue);
bbuf.rewind();
// best approach is copy the internal buffer
byte[] bytesToStore = new byte[size];
bbuf.get(bytesToStore);
writeFile(bytesToStore);
}
/**
* Write the file in Java
* @param byteArray
*/
public static void writeFile(byte[] byteArray) {
try{
File file = new File("bytebuffertest");
FileOutputStream output = new FileOutputStream(file);
IOUtils.write(byteArray, output);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Now I need to retrieve Byte Array from that same file using the below C++ program and deserialize it to extract employeeId
, lastModifiedDate
and attributeValue
from it. 现在,我需要使用以下C ++程序从同一文件中检索字节数组,并将其反序列化以从中提取
employeeId
, lastModifiedDate
和attributeValue
。 I am not sure what is the best way on the C++ side. 我不确定C ++方面的最佳方法是什么。 Below is the code I have so far:
下面是我到目前为止的代码:
int main() {
string line;
std::ifstream myfile("bytebuffertest", std::ios::binary);
if (myfile.is_open()) {
uint16_t employeeId;
uint64_t lastModifiedDate;
uint32_t attributeLength;
char buffer[8]; // sized for the biggest read we want to do
// read two bytes (will be in the wrong order)
myfile.read(buffer, 2);
// swap the bytes
std::swap(buffer[0], buffer[1]);
// only now convert bytes to an integer
employeeId = *reinterpret_cast<uint16_t*>(buffer);
cout<< employeeId <<endl;
// read eight bytes (will be in the wrong order)
myfile.read(buffer, 8);
// swap the bytes
std::swap(buffer[0], buffer[7]);
std::swap(buffer[1], buffer[6]);
std::swap(buffer[2], buffer[5]);
std::swap(buffer[3], buffer[4]);
// only now convert bytes to an integer
lastModifiedDate = *reinterpret_cast<uint64_t*>(buffer);
cout<< lastModifiedDate <<endl;
// read 4 bytes (will be in the wrong order)
myfile.read(buffer, 4);
// swap the bytes
std::swap(buffer[0], buffer[3]);
std::swap(buffer[1], buffer[2]);
// only now convert bytes to an integer
attributeLength = *reinterpret_cast<uint32_t*>(buffer);
cout<< attributeLength <<endl;
myfile.read(buffer, attributeLength);
// now I am not sure how should I get the actual attribute value here?
//close the stream:
myfile.close();
}
else
cout << "Unable to open file";
return 0;
}
I have specifically set the storage Java-side to big-endian which means I know where each byte belongs I guess. 我专门将存储Java端设置为big-endian,这意味着我知道每个字节都在哪里。 So how do I code it while shifting the bytes into the proper position for each and every value?
那么,如何在将字节移动到每个值的正确位置时进行编码? Right now I am coding it as little-endian I guess which is not what I want...
现在我正在将其编码为小端,我想这不是我想要的...
I was reading somewhere that I can use ntoh
in C++ to deserialize the Byte Array.. Not sure whether htons
will be much better solution as compared to what I have currently?.. 我在某处读书,可以在C ++中使用
ntoh
对字节数组进行反序列化。.不确定htons
是否比我目前拥有的解决方案好得多?
If yes, then I am not sure how to use that in my current C++ code? 如果是,那么我不确定如何在当前的C ++代码中使用它?
Can anybody take a look on C++ code and see what I can do to improve it, as I don't think it is looking much efficient? 谁能看看C ++代码,看看我能做些什么来改进它,因为我认为它看起来效率不高? Any better way to deserialize the Byte Array and extract relevant information on the C++ side?
还有什么更好的方法可以在C ++方面反序列化字节数组并提取相关信息?
If the Java and the C++ Code is developed by you then it's perhaps better to use the Google Protocol Buffer ( https://developers.google.com/protocol-buffers/docs/overview ) instead to write your own serializer / deserializer. 如果您是由Java和C ++代码开发的,那么最好使用Google协议缓冲区( https://developers.google.com/protocol-buffers/docs/overview )来编写自己的序列化器/反序列化器。
If you really want to write your own implementation the best way is to write a buffer class which receives the byte-stream as parameter (eg as Constructor parameter) and make some access methodes readShort / readLong / readInt / readByte ... and only swap the needed bytes. 如果您真的想编写自己的实现,最好的方法是编写一个缓冲区类,该缓冲区类将字节流作为参数(例如,构造函数参数)接收,并使某些访问方法readShort / readLong / readInt / readByte ...仅交换所需的字节。
class ByteBuffer{
explicit ByteBuffer(uint8_t* byteStream, uint16_t streamLength);
uint8_t readUInt8(uint16_t readPos)const {return m_byteStream[readPos];} // no conversion needed
uint16_t readUInt16(uint16_t readPos)const {
const uint8_t byteCount = 2;
union{
uint16_t u16;
uint8_t u8[byteCount];
}tmp;
for(uint8_t i=0; i<byteCount; ++i){
tmp.u8[i] = readUInt8(readPos+i*8);
}
return ntohs(tmp.u16); // do conversion
}
...
}
Checks for read behind the buffer is missing here. 此处缺少对缓冲区后面的读取的检查。 If your code should be portable then you have use ntohl / ntohs (see: http://forums.codeguru.com/showthread.php?298741-C-General-What-do-ntohl%28%29-and-htonl%28%29-actually-do ).
如果您的代码应该是可移植的,那么您可以使用ntohl / ntohs(请参阅: http ://forums.codeguru.com/showthread.php?298741-C-General-What-do-ntohl%28%29-and-htonl% 28%29-actually-do )。 If you swap the bytes by our own then your code is not portable (runs only on Little-Endian machines).
如果您通过我们自己交换字节,那么您的代码将不可移植(仅在Little-Endian计算机上运行)。 If you use ntoh then it would also run on a such machine.
如果您使用ntoh,那么它也可以在这样的机器上运行。
For convenience I would also write a wrapper class where you can read and write your fields (eg employeeId) directly: 为了方便起见,我还将编写一个包装器类,您可以在其中直接读写字段(例如,employeeId):
class MyBuffer{
uint16_t readEmployeeId()const{return m_Buffer.readuint16(EmployeeId_Pos);}
....
static const uint16_t EmployeeId_Pos = 0;
....
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.