我正在使用具有Big-Endian字节顺序格式的Java将字节数组值写入文件中。。现在我需要从C程序中读取该文件。。。
我正在写入文件的字节数组由三个字节数组组成,如下所述-
short employeeId = 32767;
long lastModifiedDate = "1379811105109L";
byte[] attributeValue = os.toByteArray();
我正在将employeeId
、lastModifiedDate
和attributeValue
一起写入一个单字节数组,并将生成的字节数组写入一个文件,然后我将使用我的C程序从文件中检索该字节数组数据,然后反序列化以提取employeeId
,lastModifiedDate
和它的attributeValue
。
下面是我的工作Java代码,它将字节数组值写入大端格式的文件:
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();
}
}
}
现在,我需要使用下面的C程序从同一个文件中检索字节数组,并将其反序列化以从中提取employeeId
、lastModifiedDate
和attributeValue
。我不确定在C端什么是最好的方式。以下是我目前掌握的代码:
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;
}
我已经专门将存储Java端设置为big-endian,这意味着我知道每个字节所属的位置。那么,如何在将字节移动到每个值的正确位置的同时对其进行编码呢?现在我把它编码成小endian我猜这不是我想要的。。。
我在某个地方读到,我可以用C中的ntoh
来反序列化字节数组。。不确定与我目前拥有的相比,htons
是否是更好的解决方案?。。
如果是,那么我不确定如何在我当前的C代码中使用它?
有谁能看看C代码,看看我能做些什么来改进它,因为我认为它看起来效率不高?有没有更好的方法来反序列化字节数组并在C端提取相关信息?
如果Java和C代码是由您开发的,那么最好使用Google协议缓冲区(https://developers.google.com/protocol-buffers/docs/overview)而是编写自己的序列化程序/反序列化html" target="_blank">程序。
如果您真的想编写自己的实现,最好的方法是编写一个缓冲区类,它接收字节流作为参数(例如,作为构造函数参数),并使一些访问方法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
}
...
}
此处缺少检查缓冲区后面的读取。如果您的代码应该是可移植的,那么您必须使用ntohl/ntohs(请参阅:http://forums.codeguru.com/showthread.php?298741-C-General-What-do-ntohl()-和-htonl()-实际执行)。如果您自己交换字节,那么您的代码是不可移植的(仅在Little Endian机器上运行)。如果您使用ntoh,那么它也会在这样的机器上运行。
为了方便起见,我还编写了一个包装类,您可以在其中直接读写字段(例如雇员ID):
class MyBuffer{
uint16_t readEmployeeId()const{return m_Buffer.readuint16(EmployeeId_Pos);}
....
static const uint16_t EmployeeId_Pos = 0;
....
}
问题内容: 所有, 我一直在网上练习编码问题。目前,我正在研究问题陈述“ 问题”,我们需要在其中转换大尾数<->小尾数。但是考虑到给出的示例,我无法记下步骤: 我正在考虑的逻辑是: 1>获取整数值(由于我在Windows x86上,输入为Little Endian) 2>生成相同的十六进制表示形式。 3>反转表示并生成大端整数 但是我显然在这里缺少一些东西。 谁能指导我。我正在用Java 1.5编
我目前有一个Java ByteBuffer,它已经有了Big-Endian格式的数据。然后我想写一个二进制文件作为Little Endian。 下面是刚刚用Big-Endian编写文件的代码: 请注意,byteBuff是一个以Big-Endian格式填充的ByteBuffer。 我最后的办法是使用蛮力方法创建另一个缓冲区,并将ByteBuffer设置为little endian,然后从原始(big
问题内容: 我知道我们可以 但是,这种小字节序格式很难与原始Guid进行比较 如何在SQL语句中使用原始的Guid而不是little endian? 问题答案: 如果您想轻松地与原始内容进行比较而不进行转换,则将其存储为文本。它会占用更多的存储空间,并且读/写/比较会更慢,但更容易被人阅读。
问题内容: 我能够将其转换为无符号整数: 这利用了Go包https://golang.org/src/encoding/binary/binary.go中的BigEndian和LittleEndian类型。 这提供了,但是没有等效项或 有什么想法为什么不呢?另外,应该怎么做呢? 问题答案: 将数字类型转换为一系列字节(),反之亦然,这与字节序有关。您如何解释结果完全取决于您。 您所需要做的就是汇编
问题内容: 我正在尝试编写.txt文件,它必须是UCS-2 Little Endian,但是当我尝试 根据我的阅读,它应该是相同的,但在服务器上的特定应用程序中将无法使用。当我在Notepad ++中打开可以正常工作(手动创建)的文件时,它说它是“ UCS-2 Little Endian”,但是用Java这样创建时,它说“ UCS-2 LE w / o BO”,服务器无法读取它。 我该怎么写才能使
Endian Firewall Community是一个功能齐全的Linux安全发行版本,它可以将每一种系统变成一个功能齐全的安全设备,并拥有UTM的功能。其特性包括:状态数据 包检测防火墙、多种协议(HTTP、FTP、POP3、SMTP)的应用程序级代理、支持反病毒和垃圾邮件过滤、Web通信过滤和VPN。