• Java输出小端二进制文件


    最近和C语言的系统有交互,需要给对方传输二进制文件,但C语言的文件默认是小端,而Java作为网络应用程序,默认是大端

    因此需要在写入二进制文件的时候修改一下写入字节的顺序。

    先看看普通写入

    FileOutputStream fos = new FileOutputStream("D:/temp/test.txt");
    BufferedOutputStream bos=new BufferedOutputStream(fos);
    DataOutputStream dos=new DataOutputStream(bos);
    
    dos.writeShort(66);
    
    dos.close();
    bos.close();
    fos.close();
    

    用16进制编辑器打开文件可以看到内容为

    00 42
    

    然而C语言中的顺序是小端先行,即

    42 00
    

    查看DataOutputStream.writeShort源码,其实它也是将数值分解成8位二进制(1byte)写入

    public final void writeShort(int v) throws IOException {
    	out.write((v >>> 8) & 0xFF);
    	out.write((v >>> 0) & 0xFF);
    	incCount(2);
    }
    

    故我们可以手动写入byte数组,将目标数值手动转化为一个byte数组,于是我们写一个方法

    // 小端输出模式
    public static byte[] short2Bytes(short a) {
    	return new byte[] {
    			(byte) (a & 0xFF),
    			(byte) ((a >> 8) & 0xFF)
    	};
    }
    

    修改调用,将最开始的

    dos.writeShort(66);
    

    改为

    dos.write(short2Bytes((short)66));
    

    输出文件就是小端先行了。

    上面例子是写入short。int也是同理,写一个方法手动将int转byte数组

    // 小端输出模式
    public static byte[] int2Bytes(int a) {
    	return new byte[] {
    			(byte) (a & 0xFF),
    			(byte) ((a >> 8) & 0xFF),
    			(byte) ((a >> 16) & 0xFF),
    			(byte) ((a >> 24) & 0xFF)
    	};
    }
    

    调用的时候将

    dos.writeInt(66);
    

    改为

    dos.write(int2Bytes(66));
    

    至于long,按照规律,相信读者自己可以写出来。

    最后附上完整demo代码

    package smallend;
    
    import java.io.BufferedOutputStream;
    import java.io.DataOutputStream;
    import java.io.FileOutputStream;
    
    public class SmallEndTest {
    
    	public static void main(String[] args) throws Exception {
    		FileOutputStream fos = new FileOutputStream("D:/temp/test.txt");
            BufferedOutputStream bos=new BufferedOutputStream(fos);
            DataOutputStream dos=new DataOutputStream(bos);
            
            dos.writeShort(66); // 00 42
            dos.write(short2Bytes((short)66)); // 42 00
            
            dos.writeInt(66); // 00 00 00 42
            dos.write(int2Bytes(66)); // 42 00 00 00
            
            dos.close();
            bos.close();
            fos.close();
    
    	}
    	
    	// 小端输出模式
        public static byte[] short2Bytes(short a) {
        	return new byte[] {
            		(byte) (a & 0xFF),
            		(byte) ((a >> 8) & 0xFF)
            };
        }
        
        // 小端输出模式
        public static byte[] int2Bytes(int a) {
        	return new byte[] {
            		(byte) (a & 0xFF),
            		(byte) ((a >> 8) & 0xFF),
            		(byte) ((a >> 16) & 0xFF),
            		(byte) ((a >> 24) & 0xFF)
            };
        }
    
    }
    

    吐槽一下:网上找了半天博客,方法内容一大堆,楞是不知道到底咋用【大概我领悟力太差】。最后还是自己弄出来了,特此记录一下。

  • 相关阅读:
    Docker基础 镜像,容器,仓库核心概念 常用命令和软件安装示例
    JHipster创建微服务及相关微服务架构组件介绍
    PageHelper分页插件及相关案例介绍
    DataTables API及服务端处理模式介绍和后端分页案例
    微服务概念及SpringCloud五大神兽介绍
    GitHub上重要的几个搜索技巧
    Java 内存区域详解
    莫等闲,白了少年头,空悲切!
    解决Mongoose中populate方法导致模板引擎art-template无法渲染的问题,错误-RangeError: Maximum call stack size exceeded
    vscode添加到右键菜单【win10系统】
  • 原文地址:https://www.cnblogs.com/tenny-peng/p/11847364.html
Copyright © 2020-2023  润新知