Nio Buffer Training

作者: 这是一个随便起的昵称 | 来源:发表于2018-07-08 14:59 被阅读11次

    上一篇 学习了,ByteBuffer 的一些重要的 Api,这篇借着所学习的知识完成一个小小的Demon

    一般我们的数据传输都是明文传输,采用各种各样的格式,如 JSON,XML等。现在就用上篇所学的 Api 来完成一个定制的字节流数据传输格式。即把我们所需要传输的数据以特定的格式(有一定的加密效果)生成,再以特定的格式解析。需要注意的是这个Demon有很大的改进空间。目前只支持以固定顺序读取数据,可以继续改进,读取任意一个数据(重新定义数据格式)。

    先来介绍一下基本思路。

    1. 制定特定的数据格式
      | type | length | content |
      type 单个数据的格式(见代码)
      length 数据的长度或 array类型的length。基本数据类型没有长度这个字段。
      content 即内容(byte 字节流)
    2. 以特定的顺序写入数据
      writeInt()
      writeIntArray()
      writeDouble()
      ...
    3. 以特定的顺序读取数据
    package com.zsy.nio;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.nio.ByteBuffer;
    import java.util.Arrays;
    
    public class NIOTraining {
    
        public static void main(String[] args) throws UnsupportedEncodingException, IOException {
            TransData transData = new TransData();
            byte[] bytes = transData
                    .writeInt(165)
                    .writeDouble(165.2)
                    .writeString("hello world!")
                    .writeIntArray(new int[] {85,89,56})
                    .writeStringArray(new String[] {"zhongguo","nanjing","Java"})
                    .getData();
        
    
            ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
    
            while (byteBuffer.hasRemaining()) {
                switch (byteBuffer.get()) {
                    case TransData.TYPE_INT:
                        System.out.println(byteBuffer.getInt());
                        break;
                    case TransData.TYPE_DOUBLE:
                        System.out.println(byteBuffer.getDouble());
                        break;
                    case TransData.TYPE_STRING:
                        int length = byteBuffer.getInt();
                        System.out.println(new String(byteBuffer.array(),byteBuffer.position(), length, "UTF-8"));
                        byteBuffer.position(byteBuffer.position() + length);
                        break;
                    case TransData.TYPE_ARRAY_INT:
                        int len = byteBuffer.getInt();
                        int[] results = new int[len];
                        for(int i=0; i<len; i++) {
                            results[i] = byteBuffer.getInt();
                        }
                        System.out.println(Arrays.toString(results));
                        break;
                    case TransData.TYPE_ARRAY_STRING:
                        int stringsLength = byteBuffer.getInt();
                        String[] strings = new String[stringsLength];
                        for(int i=0; i<stringsLength; i++) {
                            int stringLen = byteBuffer.getInt();
                            strings[i] = new String(byteBuffer.array(), byteBuffer.position(), stringLen, "UTF-8");
                            byteBuffer.position(byteBuffer.position() + stringLen);
                        }
                        System.out.println(Arrays.toString(strings));
                        break;
                }
            }
    
        }
    
        /**
         * |type|length|content| type 1 byte length 4 byte 基本类型不需要 length
         * 
         * @author zhaoxiaosi
         *
         */
        static class TransData {
    
            private static final byte TYPE_INT = 1;
            private static final byte TYPE_DOUBLE = 2;
            private static final byte TYPE_STRING = 3;
    
            private static final byte TYPE_ARRAY_STRING = 4;
            private static final byte TYPE_ARRAY_INT = 5;
            private static final byte TYPE_ARRAY_DOUBLE = 6;
    
            private ByteArrayOutputStream out = new ByteArrayOutputStream();
    
            public TransData writeInt(int content) {
                out.write(TYPE_INT);
                out.write(content >>> 24);
                out.write(content >>> 16);
                out.write(content >>> 8);
                out.write(content);
                return this;
            }
            
            public TransData writeIntArray(int[] ints) {
                out.write(TYPE_ARRAY_INT);
                writeLength(ints.length);
                for(int i: ints) {
                    out.write(i >>> 24);
                    out.write(i >>> 16);
                    out.write(i >>> 8);
                    out.write(i);
                }
                return this;
            }
            
            public TransData writeStringArray(String[] strings) throws IOException {
                out.write(TYPE_ARRAY_STRING);
                writeLength(strings.length);
                for(String string: strings) {
                    byte[] bytes = string.getBytes("UTF-8");
                    writeLength(bytes.length);
                    out.write(bytes);
                }
                return this;
            }
    
            public TransData writeDouble(double content) {
                long value = Double.doubleToRawLongBits(content);
                out.write(TYPE_DOUBLE);
                out.write((byte) (int)value >>> 56);
                out.write((byte) (int)value >>> 48);
                out.write((byte) (int)value >>> 40);
                out.write((byte) (int)value >>> 32);
                out.write((byte) (int)value >>> 24);
                out.write((byte) (int)value >>> 16);
                out.write((byte) (int)value >>> 8);
                out.write((byte) (int)value);
                return this;
            }
            
    
            public TransData writeString(String content) throws UnsupportedEncodingException, IOException {
                out.write(TYPE_STRING);
                byte[] bytes = content.getBytes("UTF-8");
                writeLength(bytes.length);
                out.write(bytes);
                return this;
            }
            
            private void writeLength(int length) {
                out.write(length >>> 24);
                out.write(length >>> 16);
                out.write(length >>> 8);
                out.write(length);
            }
    
            public byte[] getData() {
                return out.toByteArray();
            }
    
        }
    }
    
    

    output

    165
    2.16443570729E-312
    hello world!
    [85, 89, 56]
    [zhongguo, nanjing, Java]
    

    相关文章

      网友评论

        本文标题:Nio Buffer Training

        本文链接:https://www.haomeiwen.com/subject/zzjouftx.html