Java中的Big/Little问题
1. 解决Endian问题:一个总结
Java二进制文件中的所有东西都以big-endian形式存在,高字节优先,这有时被称为网络顺序。这是一个好的消息,意味着假如你只使用Java。所有文件在所有平台(Mac,PC,Solaris等)上按同样的方式进行处理。可以自由地交换二进制数据,以电子形式在Internet上,或在软盘上,而无需考虑endian问题。存在的问题是当你与那些不是使用Java编写的程序交换数据文件时,会存在一些问题。因为这些程序使用的是little-endian顺序,通常是在PC上使用的C语言。有些平台内部使用big-endian字节顺序(Mac,IBM390);有些平台使用little-endian字节顺序(Intel)。Java对用户隐瞒了endian问题。
在二进制文件中,在域之间没有分割符,文件是二进制形式的,不可读的ASCII。假如你想读的数据不是标准格式,通常由非Java程序预备的。可以由四种选择:
1). 重写提供输入文件的输出程序。它可以直接输出big-endian字节流DataOutputStream或者字符DataOutputSream格式。
2). 写一个独立的翻译程序,读和排列字节。可以用任何语言编写。
3). 以字节形式读数据,并重新安排它们(on the fly)。
4). 最简单的方式是,使用我编写的LEDataInputStream, LEDataOutputStream 和LERandomAccessFile模拟 DataInputStream, DataOutputStream and RandomAccessFile ,它们使用的是little-endian字节流。 You can read about LEDataStream. You can download the code and source free. You can get help from the File I/O Amanuensis to show you how to use the classes. Just tell it you have little-endian binary data.
2.你可能甚至不会有任何问题。
从C来的许多Java新手可能会认为需要考虑它们所依靠的平台内部所使用的是big还是little问题。在Java中这不是一个问题。进一步,不借助于本地类,你无法知道它们是如何存储的。Java has no strUCt I/O and no unions or any of the other endian-sensitive language constructs.
仅在与遗留的C/C++应用程序通讯时需要考虑endian问题。下列代码在big or little endian机器上都将产生同样的结果:
// take 16-bit short apart into two 8-bit bytes.
short x = 0xabcd;
byte high = (byte) (x >>> 8);
byte low = (byte) x;/* cast implies & 0xff */
System.out.println ("x=" + x + " high=" + high + " low=" + low );
3.读Little-Endian Binary Files
The most common problem is dealing with files stored in little-endian format.
I had to implement routines parallel to those in java.io.DataInputStream which reads raw binary, in my LEDataInputStream and LEDataOutputStream classes. Don't confuse this with the io.DataInput human-readable character-based file-interchange format.
If you wanted to do it yourself, without the overhead of the full LEDataInputStream and LEDataOutputStream classes, here is the basic technique:
Presuming your integers are in 2's complement little-endian format, shorts are pretty easy to handle:
--------------------------------------------------------------------------------
short readShortLittleEndian( )
{
// 2 bytes
int low = readByte() & 0xff;
int high = readByte() & 0xff;
return (short )(high << 8 low);