转自
http://blogger.org.cn/blog/more.asp?name=hongrui&id=23869
java是与CPU无关的编程语言,但是java究竟是little-endian还是big-endian呢,因为java诞生于soalris
平台,最初的solaris运行于SPARC cpu上,SUN的SPARC和IBM的POWER
PC均是big-endian,所以java也是big-endian。
判断java是big endian的代码
public final static int swabInt(int v)
{
return (v
>>> 24) | (v
<< 24) |
((v <<
8) & 0x00FF0000) | ((v
>> 8) &
0x0000FF00);
}
public static void main(String argv[])
{
// before 0x01020304
// after 0x04030201
int v = 0x01020304;
System.out.println("before : 0x"
+ Integer.toString(v,16));
System.out.println("after : 0x" + Integer.toString(swabInt(v),16));
}
// take 16-bit short apart into two 8-bit bytes.
short x = 0xabcd;
byte high = (byte)(x
>>> 8);
byte low = (byte)x;
System.out.println( "x=" + x + " high=" + high + " low=" + low
);
big endian是指低地址存放最高有效字节(MSB),而little
endian则是低地址存放最低有效字节(LSB)。
Big Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 12 | 34 | 56 | 78 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 78 | 56 | 34 | 12 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
如果你做单机程序,这个基本不用考虑,如何和java程序通讯也没有问题,java中在AIX下生成的对象被序列化后能够在windows下正确的反序列化,如果不这样,EJB也就不存在了。
如果你和C++的程序通讯,问题就有了,C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而JAVA编写的程序则唯一采用big
endian方式来存储数据。
你在x86平台上,使用c语言通过socket把0x12345678发给java的serversocket,得到的是0x78563412,C程序传给JAVA程序之前有必要进行字节序的转换工作。
所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把big
endian方式称之为网络字节序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。
c/c++中发送方htonl,接收方ntohl。
fseek(f,0L,SEEK_END); unsigned int tcount=total;
tcount=htonl(tcount);
memcpy( &buffer[1], &tcount,
4);
Java中不用做转换。
DataOutputStream.writeInt();
DataInputStream.readInt();
c语言转换的4个宏
ntoh:network->host
hton:host->network
ntohs和htons针对2字节的数
ntohl和htonl针对4字节的数
为了保证代码的移植性,必须用这两个函数。
htons(): reorder the bytes of a 16-bit unsigned
value from processor order to network order. The macro name can be
read "host to network short."
htonl(): reorder the bytes of a 32-bit unsigned
value from processor order to network order. The macro name can be
read "host to network long."
ntohs(): reorder the bytes of a 16-bit unsigned
value from network order to processor order. The macro name can be
read"network to host short."
ntohl(): reorder the bytes of a 32-bit unsigned
value from network order to processor order. The macro name can be
read "network to host long."
#if defined(BIG_ENDIAN) &&
!defined(LITTLE_ENDIAN)
#define htons(A) (A)
#define htonl(A) (A)
#define ntohs(A) (A)
#define ntohl(A) (A)
#elif defined(LITTLE_ENDIAN) &&
!defined(BIG_ENDIAN)
#define htons(A) ((((uint16)(A) & 0xff00)
>> 8) | \
(((uint16)(A) & 0x00ff)
<< 8))
#define htonl(A) ((((uint32)(A) & 0xff000000)
>> 24) | \
(((uint32)(A) & 0x00ff0000)
>> 8) | \
(((uint32)(A) & 0x0000ff00)
<< 8) | \
(((uint32)(A) & 0x000000ff)
<< 24))
#define ntohs htons
#define ntohl htohl
#else
#error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but
not both."
#endif
但是如果不是走网络,c语言把结构直接写入了文件,那末java读Little Endian 就麻烦一些,这方面的代码很多。
使用jdk1.4以后的版本,
float f = ByteBuffer.wrap( array ).order( ByteOrder.LITTLE_ENDIAN
).getFloat();
否则就得自己写代码了
package com.mindprod.ledatastream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class LEDataOutputStream implements DataOutput
{
// ------------------------------ FIELDS
------------------------------
byte w[];
protected DataOutputStream d;
// -------------------------- STATIC METHODS
--------------------------
public static final String getCopyright()
{
return "LeDataStream 1.7
freeware copyright (c) 1998-2007 Roedy Green, Canadian Mind
Products, http://mindprod.comroedyg@mindprod.com";
}
// --------------------------- CONSTRUCTORS
---------------------------
public LEDataOutputStream( OutputStream out
)
{
this.d = new
DataOutputStream( out );
w = new byte[8];// work
array for composing output
}
// ------------------------ INTERFACE METHODS
------------------------
// --------------------- Interface DataOutput
---------------------
public final synchronized void write( int b )
throws IOException
{
d.write( b );
}
public final void write( byte b[] ) throws
IOException
{
d.write( b, 0, b.length
);
}
public final synchronized void write( byte
b[],
int off,
int len ) throws IOException
{
d.write( b, off, len
);
}
public final void writeBoolean( boolean v )
throws IOException
{
d.writeBoolean( v
);
}
// p u r e l y w r a p p e r m e t h o d
s
// We cannot inherit since DataOutputStream is
final.
public final void writeByte( int v ) throws
IOException
{
d.writeByte( v );
}
public final void writeShort( int v ) throws
IOException
{
w[ 0 ] = (byte) v;
w[ 1 ] = (byte) ( v
>> 8 );
d.write( w, 0, 2
);
}
public final void writeChar( int v ) throws
IOException
{
// same code as
writeShort
w[ 0 ] = (byte) v;
w[ 1 ] = (byte) ( v
>> 8 );
d.write( w, 0, 2
);
}
public final void writeInt( int v ) throws
IOException
{
w[ 0 ] = (byte) v;
w[ 1 ] = (byte) ( v
>> 8 );
w[ 2 ] = (byte) ( v
>> 16 );
w[ 3 ] = (byte) ( v
>> 24 );
d.write( w, 0, 4
);
}
public final void writeLong( long v ) throws
IOException
{
w[ 0 ] = (byte) v;
w[ 1 ] = (byte) ( v
>> 8 );
w[ 2 ] = (byte) ( v
>> 16 );
w[ 3 ] = (byte) ( v
>> 24 );
w[ 4 ] = (byte) ( v
>> 32 );
w[ 5 ] = (byte) ( v
>> 40 );
w[ 6 ] = (byte) ( v
>> 48 );
w[ 7 ] = (byte) ( v
>> 56 );
d.write( w, 0, 8
);
}
public final void writeFloat( float v ) throws
IOException
{
writeInt(
Float.floatToIntBits( v ) );
}
public final void writeDouble( double v ) throws
IOException
{
writeLong(
Double.doubleToLongBits( v ) );
}
public final void writeBytes( String s ) throws
IOException
{
d.writeBytes( s );
}
public final void writeChars( String s ) throws
IOException
{
int len =
s.length();
for ( int i = 0; i
< len; i++ )
{
writeChar( s.charAt( i ) );
}
}// end
writeChars
public final void writeUTF( String str ) throws
IOException
{
d.writeUTF( str );
}
// -------------------------- OTHER METHODS
--------------------------
// L I T T L E E N D I A N W R I T E R
S
// Little endian methods for multi-byte numeric
types.
// Big-endian do fine for single-byte types and
strings.
public final void close() throws
IOException
{
d.close();
}
// DataOutputStream
public void flush() throws IOException
{
d.flush();
}
public final int size()
{
return d.size();
}
}// end LEDataOutputStream
package com.mindprod.ledatastream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
public class LEDataInputStream implements DataInput
{
// ------------------------------ FIELDS
------------------------------
byte w[];
protected DataInputStream d;
protected InputStream in;
// -------------------------- STATIC METHODS
--------------------------
public static final String getCopyright()
{
return "LeDataStream 1.7
freeware copyright (c) 1998-2007 Roedy Green, Canadian Mind
Products, http://mindprod.comroedyg@mindprod.com";
}
public final static String readUTF( DataInput in
) throws IOException
{
return
DataInputStream.readUTF( in );
}
// --------------------------- CONSTRUCTORS
---------------------------
// i n s t a n c e v a r i a b l e s
public LEDataInputStream( InputStream in )
{
this.in = in;
this.d = new
DataInputStream( in );
w = new byte[8];
}
// ------------------------ INTERFACE METHODS
------------------------
// --------------------- Interface DataInput
---------------------
public final void readFully( byte b[] ) throws
IOException
{
d.readFully( b, 0,
b.length );
}
public final void readFully( byte b[], int off,
int len ) throws IOException
{
d.readFully( b, off, len
);
}
public final int skipBytes( int n ) throws
IOException
{
return d.skipBytes( n
);
}
public final boolean readBoolean() throws
IOException
{
return
d.readBoolean();
}
public final byte readByte() throws
IOException
{
return
d.readByte();
}
public final int readUnsignedByte() throws
IOException
{
return
d.readUnsignedByte();
}
// L I T T L E E N D I A N R E A D E R
S
// Little endian methods for multi-byte numeric
types.
// Big-endian do fine for single-byte types and
strings.
public final short readShort() throws
IOException
{
d.readFully( w, 0, 2
);
return (short) ( ( w[ 1
] & 0xff ) << 8 | (
w[ 0 ] & 0xff ) );
}
public final int readUnsignedShort() throws
IOException
{
d.readFully( w, 0, 2
);
return ( ( w[ 1 ]
& 0xff ) << 8 | ( w[
0 ] & 0xff ) );
}
public final char readChar() throws
IOException
{
d.readFully( w, 0, 2
);
return (char) ( ( w[ 1 ]
& 0xff ) << 8 | ( w[
0 ] & 0xff ) );
}
public final int readInt() throws
IOException
{
d.readFully( w, 0, 4
);
return ( w[ 3 ] )
<< 24
| ( w[ 2 ] & 0xff )
<< 16
| ( w[ 1 ] & 0xff )
<< 8
| ( w[ 0 ] & 0xff );
}
public final long readLong() throws
IOException
{
d.readFully( w, 0, 8
);
return (long) ( w[ 7 ] )
<< 56
|
(long) ( w[ 6 ] & 0xff )
<< 48
| (long) ( w[ 5 ] & 0xff )
<< 40
| (long) ( w[ 4 ] & 0xff )
<< 32
| (long) ( w[ 3 ] & 0xff )
<< 24
| (long) ( w[ 2 ] & 0xff )
<< 16
| (long) ( w[ 1 ] & 0xff )
<< 8
| (long) ( w[ 0 ] & 0xff );
}
public final float readFloat() throws
IOException
{
return
Float.intBitsToFloat( readInt() );
}
public final double readDouble() throws
IOException
{
return
Double.longBitsToDouble( readLong() );
}
public final String readLine() throws
IOException
{
return
d.readLine();
}
public final String readUTF() throws
IOException
{
return
d.readUTF();
}
// -------------------------- OTHER METHODS
--------------------------
public final void close() throws
IOException
{
d.close();
}
// InputStream
// p u r e l y w r a p p e r m e t h o d
s
// We can't simply inherit since dataInputStream
is final.
public final int read( byte b[], int off, int
len ) throws IOException
{
// For efficiency, we
avoid one layer of wrapper
return in.read( b, off,
len );
}
}// end class LEDataInputStream
java io的代码
package com.macfaq.io;
import java.io.*;
public class LittleEndianOutputStreamextends FilterOutputStream
{
protected int written;
public LittleEndianOutputStream(OutputStream out)
{
super(out);
}
public synchronized void write(int b) throws IOException
{
out.write(b);
written++;
}
public synchronized void write(byte[] data, int offset, int
length)
throws IOException {
out.write(data, offset, length);
written += length;
}
public void writeBoolean(boolean b) throws IOException
{
if (b) this.write(1);
else this.write(0);
}
public void writeByte(int b) throws IOException
{
out.write(b);
written++;
}
public void writeShort(int s) throws IOException
{
out.write(s & 0xFF);
out.write((s
>>> 8)
& 0xFF);
written += 2;
}
public void writeChar(int c) throws IOException
{
out.write(c & 0xFF);
out.write((c
>>> 8)
& 0xFF);
written += 2;
}
public void writeInt(int i) throws IOException
{
out.write(i & 0xFF);
out.write((i
>>> 8)
& 0xFF);
out.write((i
>>> 16)
& 0xFF);
out.write((i
>>> 24)
& 0xFF);
written += 4;
}
public void writeLong(long l) throws IOException
{
out.write((int) l &
0xFF);
out.write((int) (l
>>> 8)
& 0xFF);
out.write((int) (l
>>> 16)
& 0xFF);
out.write((int) (l
>>> 24)
& 0xFF);
out.write((int) (l
>>> 32)
& 0xFF);
out.write((int) (l
>>> 40)
& 0xFF);
out.write((int) (l
>>> 48)
& 0xFF);
out.write((int) (l
>>> 56)
& 0xFF);
written += 8;
}
public final void writeFloat(float f) throws IOException
{
this.writeInt(Float.floatToIntBits(f));
}
public final void writeDouble(double d) throws IOException
{
this.writeLong(Double.doubleToLongBits(d));
}
public void writeBytes(String s) throws IOException
{
int length = s.length();
for (int i = 0; i < length; i++)
{
out.write((byte) s.charAt(i));
}
written += length;
}
public void writeChars(String s) throws IOException
{
int length = s.length();
for (int i = 0; i < length; i++)
{
int c = s.charAt(i);
out.write(c &
0xFF);
out.write((c
>>> 8)
& 0xFF);
}
written += length * 2;
}
public void writeUTF(String s) throws IOException
{
int numchars = s.length();
int numbytes = 0;
for (int i = 0 ; i < numchars
; i++) {
int c = s.charAt(i);
if ((c >= 0x0001)
&& (c <= 0x007F))
numbytes++;
else if (c > 0x07FF)
numbytes += 3;
else numbytes += 2;
}
if (numbytes > 65535) throw
new UTFDataFormatException();
out.write((numbytes
>>> 8)
& 0xFF);
out.write(numbytes &
0xFF);
for (int i = 0 ; i < numchars ;
i++) {
int c = s.charAt(i);
if ((c >= 0x0001)
&& (c <= 0x007F))
{
out.write(c);
}
else if (c > 0x07FF)
{
out.write(0xE0 | ((c
>> 12) &
0x0F));
out.write(0x80 | ((c
>> 6) &
0x3F));
out.write(0x80 | (c
& 0x3F));
written += 2;
}
else {
out.write(0xC0 | ((c
>> 6) &
0x1F));
out.write(0x80 | (c
& 0x3F));
written += 1;
}
}
written += numchars + 2;
}
/**
* Returns the number of bytes written to this little
endian output stream.
* (This class is not thread-safe with respect to this
method. It is
* possible that this number is temporarily less than
the actual
* number of bytes written.)
&