`

c和java中的二进制文件

阅读更多
最近需要写一段程序,完成以下的工作,用java将数据以二进制的形式写入文件中,然后用C读出此二进制文件。

开始的时候没有考虑机器的字节序,直接搞出segment fault.想了很久,才明白原来是java和C的字节序是不一样的。

java中的字节序是big endian的,它是与机器无关的。而c的字机序是机器相关的,而当前用的机器是x84_64结构,是little endian的,
所以出错就不足为奇了。

背景知识:

主机字节序

不同的CPU有不同的字节序类型 这些字节序是指整数在内存中保存的顺序 这个叫做主机序
最常见的有两种
1. Little endian:将低序字节存储在起始地址
2. Big endian:将高序字节存储在起始地址

LE little-endian
最符合人的思维的字节序
地址低位存储值的低位
地址高位存储值的高位
怎么讲是最符合人的思维的字节序,是因为从人的第一观感来说
低位值小,就应该放在内存地址小的地方,也即内存地址低位
反之,高位值就应该放在内存地址大的地方,也即内存地址高位

BE big-endian
最直观的字节序
地址低位存储值的高位
地址高位存储值的低位
为什么说直观,不要考虑对应关系
只需要把内存地址从左到右按照由低到高的顺序写出
把值按照通常的高位到低位的顺序写出
两者对照,一个字节一个字节的填充进去

例子:在内存中双字0x01020304(DWORD)的存储方式

内存地址
4000 4001 4002 4003
LE 04 03 02 01
BE 01 02 03 04

例子:如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x23 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12
x86系列CPU都是little-endian的字节序.

网络字节序
网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。

为了进行转换 bsd socket提供了转换的函数 有下面四个
htons 把unsigned short类型从主机序转换到网络序
htonl 把unsigned long类型从主机序转换到网络序
ntohs 把unsigned short类型从网络序转换到主机序
ntohl 把unsigned long类型从网络序转换到主机序

在使用little endian的系统中 这些函数会把字节序进行转换
在使用big endian类型的系统中 这些函数会定义成空宏

同样 在网络程序开发时 或是跨平台开发时 也应该注意保证只用一种字节序 不然两方的解释不一样就会产生bug.

注:
1、网络与主机字节转换函数:htons ntohs htonl ntohl (s 就是short l是long h是host n是network)
2、不同的CPU上运行不同的操作系统,字节序也是不同的,参见下表。
处理器 操作系统 字节排序
Alpha 全部 Little endian
HP-PA NT Little endian
HP-PA UNIX Big endian
Intelx86 全部 Little endian <-----x86系统是小端字节序系统
Motorola680x() 全部 Big endian
MIPS NT Little endian
MIPS UNIX Big endian
PowerPC NT Little endian
PowerPC 非NT Big endian <-----PPC系统是大端字节序系统
RS/6000 UNIX Big endian
SPARC UNIX Big endian
IXP1200 ARM核心 全部 Little endian

Java字节序
java语言是sun搞出来了,自然得跟sparc机器一样,属于big endian,需要说明的是,它是跟机器无关的,这点由JVM来保证,所以保证了
你一次编写,处处运行

java中将二进制转化成little endian

说了这么多废话,回到主题,怎样在java程序中用将二进制格式转化成little endian了,主要是用到了byte数组,好了,废话不多说,直接
上程序

public static int convertIntBigToLittle(int data){

int offset = 0;
byte [] array = new byte[4];

array[offset+3] = (byte)((data >>> 24) & 0xFF);
array[offset+2] = (byte)((data >>> 16) & 0xFF);
array[offset+1] = (byte)((data >>> 8) & 0xFF);
array[offset] = (byte)((data >>> 0) & 0xFF);

int ch1 = array[offset];
int ch2 = array[offset+1];
int ch3 = array[offset+2];
int ch4 = array[offset+3];
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

public static long convertLongBigToLittle( long data) {

int offset = 0;
byte [] array = new byte[8];

array[offset+7] = (byte)(data >>> 56);
array[offset+6] = (byte)(data >>> 48);
array[offset+5] = (byte)(data >>> 40);
array[offset+4] = (byte)(data >>> 32);
array[offset+3] = (byte)(data >>> 24);
array[offset+2] = (byte)(data >>> 16);
array[offset+1] = (byte)(data >>> 8);
array[offset+0] = (byte)(data >>> 0);

return (((long)array[offset] << 56) +
((long)(array[offset+1] & 255) << 48) +
((long)(array[offset+2] & 255) << 40) +
((long)(array[offset+3] & 255) << 32) +
((long)(array[offset+4] & 255) << 24) +
((array[offset+5] & 255) << 16) +
((array[offset+6] & 255) << 8) +
((array[offset+7] & 255) << 0));
}
分享到:
评论

相关推荐

    C++,java读写二进制文件方法介绍.pdf

    C++,java读写二进制文件方法介绍.pdf java从第九页开始

    java读取二进制文件

    在Java中,可以通过多种方式来读取二进制文件,其中最常用的是使用`FileInputStream`和`DataInputStream`类。这两种类都位于`java.io`包中。 1. **`FileInputStream`**:提供了基本的字节流输入功能。 2. **`...

    java的二进制操作

    在Java编程语言中,对二进制文件的操作是非常常见的需求之一,尤其是在处理图像、音频等非文本数据时。Java的标准库`java.io`提供了丰富的API来支持这些操作,其中`OutputStream`及其子类是进行二进制数据写入的核心...

    如何向MYSQL中写入二进制文件

    在实际开发中,我们经常需要将二进制文件存储在数据库中,以便于后续的使用和管理。在这篇文章中,我们将介绍如何通过Java或JSP向MYSQL数据库中写入二进制文件。 首先,我们需要了解MYSQL存储大容量的二进制文件的...

    Java把十进制转成二进制(任意进制)的程序

    在Java编程语言中,将十进制数转换为二进制或其他任意进制是一项常见的任务。这主要涉及到数字系统的基础理论以及Java中的字符串处理和数学运算。以下将详细讲解如何实现这一功能。 首先,让我们从最基础的二进制...

    HTTP二进制

    在这样的系统中,可能会涉及到上传和下载二进制文件,例如合同文档、图片等。通常,这类系统会提供API接口,允许用户通过HTTP请求提交或获取二进制数据,并且需要正确处理“Content-Type”头部以确保数据的正确解析...

    JavaClass二进制文件加密专家

    系统介绍 JavaClass文件加密专家是一款针对Java应用程序Class二进制文件加密的软件,系统核心由纯C语言编写,运行效率极 高。传统的Java程序加密的方式多为代码混迹方式,但是无论多么复杂的混迹方式,...

    二进制与字符串之间的转换类CBinary

    3. **读取二进制文件**:`CBinary`可能提供方法读取二进制文件,将文件内容加载到内存中,以二进制数据的形式进行处理。这在处理图像、音频、视频或任何非文本数据时非常有用。 4. **写入二进制文件**:与读取相对...

    NetBeans 源代码和二进制构建文件

    在实际开发中,NetBeans的源代码和二进制文件还可能用于以下场景: 1. **自定义插件开发**:开发者可以基于源码创建新的插件,扩展NetBeans的功能。 2. **本地化**:如果“ml”表示多语言,那么源代码可能包含对不同...

    WebService二进制处理

    在"JAX-WS_Upload_Client"文件中,我们可以看到一个示例客户端代码,它展示了如何使用JAX-WS调用支持MTOM的Web服务来上传二进制文件。客户端首先会创建一个包含二进制数据的流对象,然后通过Web服务接口的特定方法将...

    将二进制转换为16进制

    在计算机科学中,数据通常以不同的进制表示,如二进制(Binary)、八进制(Octal)、十进制(Decimal)和十六进制(Hexadecimal)。这些进制之间的转换是理解和操作数字系统的基础。本篇文章将深入探讨二进制与十六...

    Java中文件IO流.pdf

    文件流是指在程序中用于文件输入输出的对象, Java 中提供了多种文件流类型,包括 InputStream 和 OutputStream 两大类。 InputStream 是 Java 中的输入流接口,用于读取文件的内容,常用的 InputStream 子类包括 ...

    Java进制转换实现

    本文将深入探讨Java中如何进行进制转换,包括二进制、八进制、十进制和十六进制之间的转换。这对于任何对Java感兴趣或者正在学习Java的开发者来说都是必备的知识点。 首先,我们来看一下如何在Java中进行基本的进制...

    jtool二进制文件分析工具

    在IT领域,特别是软件开发和系统分析中,对二进制文件的理解和分析至关重要。jtool就是这样一款专为Java开发者设计的二进制文件分析工具,它能够帮助用户深入理解Java字节码,进行类文件的反编译、混淆代码的解析...

    【nexus二进制库Jar包批量上传脚本工具】

    标题中的“nexus二进制库Jar包批量上传脚本工具”是指用于自动化上传Java的JAR文件到Nexus仓库的脚本程序。Nexus是一个流行的仓库管理器,广泛应用于软件开发环境中,尤其是Java生态系统,它能管理和分发各种类型的...

    bitmap或者png转.rgba二进制文件

    `bitmap`和`png`是两种常见的图像格式,而将它们转换为`.rgba`二进制文件则涉及到图像数据的处理和理解。`.rgba`文件通常指的是包含红、绿、蓝和透明度(Alpha)通道的原始像素数据,这种格式在进行图像处理和渲染时...

    bin文件转换成十六进制数组

    在电子工程和软件开发领域,经常需要处理各种二进制文件,其中bin文件是一种常见的格式,通常用于存储程序代码或数据。"bin文件转换成十六进制数组"这个主题是关于将二进制数据转化为更适合编程和烧录的十六进制表示...

    用于 mach-o 二进制文件的 dylib 注入器.zip

    在计算机科学领域,特别是在操作系统和软件开发中,dylib注入技术是一种高级的技术操作,它涉及到将动态库(dylib文件)注入到现有的mach-o格式二进制文件中。mach-o文件格式是苹果操作系统macOS以及iOS、watchOS、...

    Java二进制Class文件格式解析

    Java二进制Class文件是Java程序的核心组成部分,它包含了Java类或接口的完整定义和元数据,被Java虚拟机(JVM)用来加载并执行代码。《The JavaTM Virtual Machine Specification》(Second Edition)和《Inside the ...

    圆柱绕流程序,结果为tecplot文件_.c程序结果用tecplot, fortran输出二进制数据到tecplot-Java文

    在这个程序中,"fortran输出二进制数据到tecplot"意味着用FORTRAN编程语言编写了一个部分,将计算得到的流场数据以二进制格式输出,便于用Tecplot进行后续的可视化分析。 描述中提到的"fluid_1157955622.f"可能是...

Global site tag (gtag.js) - Google Analytics