[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[转帖]java写二进制文件考虑一下字节顺

上一篇:[备忘]Eclipse的SVN插件就要用subclipse--强烈推荐,Subversive去死。
下一篇:[转帖]不要用字符串做同步锁Don't use String literals for the synchronized blocks

添加日期:2011/6/3 17:12:32 快速返回   返回列表 阅读5075次
http://agilejava.blogbus.com/logs/40046103.html

一直以来都在用java编程,以前在Java写一些二进制格式的文件,就用DataOutputStream很方法,例如它的writeInt,writeLong等,我今天在看一些代码的时候发现DataOutputStream在处理多字节的数字的时候,使用的是BIG_ENDIAN(即将高位的字节放在内存地址的低地址上),相应的DataInputStream的读取方式也使用的是BIG_ENDIAN。

这样就引出一个问题,如果我是用Java之外的语言,比如C语言读取由DataOutputStream生成的文件,而平台正好是LITTLE_ENDIAN(用得很广泛的x86的系统都是LITTLE_ENDIAN),很可能会造成数据错误,除非在C程序中自己重新按照BIG_ENDIAN的格式组装int或者long.

这样我们需要在写文件的时候就按照平台的字节顺来写,而ByteBuffer已经考虑到了这一点。

java.nio.ByteBuffer默认是BIG_ENDIAN(这可能和ByteBuffer主要用来做网络通讯有关),但是这个值是可以修改的。

比较使用DataOutputStream和ByteBuffer写文件的差异:


public static void main(String[] args) throws IOException {
        int _int = 12345678;
        ByteBuffer _nbuffer = ByteBuffer.allocate(4);
        _nbuffer.order(ByteOrder.nativeOrder());  //将新建的ByteBuffer设置为本机的字节顺
        _nbuffer.putInt(_int);
        _nbuffer.flip();

        FileOutputStream _fou = new FileOutputStream("test_dout.data");
        FileOutputStream _nfou = new FileOutputStream("test_nbuf.data");
        DataOutputStream _dou = new DataOutputStream(_fou);

        _dou.writeInt(_int);
        _dou.close();
        
        _nfou.write(_nbuffer.array());
        _nfou.close();
        System.out.println(ByteOrder.nativeOrder());
    }


执行上面的代码生成两个文件:

test_dout.data - 使用DataOutputStream生成的BIG_ENDIAN文件,

test_nbuf.data - 使用ByteBuffer生成的主机字节顺的文件(此处的主机字节顺为LITTLE_ENDIAN)

使用下面的C程序分别读取这两个文件:


#include <stdio.h>
int read_file(char* file);
main()
{
  char* dout = "test_dout.data";
  char* nbuf = "test_nbuf.data";
  printf("data in %s:%d\n",dout,read_file(dout));
  printf("data in %s:%d\n",nbuf,read_file(nbuf));
}
int read_file(char* file)
{
  FILE *fp;
  int dat[1];
  fp=fopen(file, "rb");/*打开一个二进制文件只读*/
  fread(dat, sizeof(int), 1, fp);
  fclose(fp);
  return dat[0];
}


编译并执行:

gcc a.c

./a.out 
data in test_dout.data:1315027968
data in test_nbuf.data:12345678

上面的C程序从test_dout.data取得的int数值是错误的,而从test_nbuf.data是正确的。

ByteBuffer不方便的地方在于它的大小不能自动扩展,但是也是可以解决的,比如MINA自己的ByteBuffer就支持自成扩展。

Java的生成二进制数据文件,应该要考虑一下字节顺的问题,以适应一些特殊的需求,比如多语言平台编程的情况。
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved