zoukankan      html  css  js  c++  java
  • 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)
            };
        }
    
    }
    

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

  • 相关阅读:
    010 --- 第14章 观察者模式
    009 --- 第13章 建造者模式
    008 --- 第12章 外观模式
    007 --- 第10章 模板方法模式
    006 --- 第9章 原型模式
    redis lua 中keys[1] 和argv[1] 的理解
    redis 入门总结
    mysql 8.0 特性简单总结
    MySql事务隔离级别 浅见
    浅谈Java中的String、StringBuffer、StringBuilder
  • 原文地址:https://www.cnblogs.com/tenny-peng/p/11847364.html
Copyright © 2011-2022 走看看