Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/196.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何聚合两个字符串和一个列表<;字节[]>;转换为单个字节[],然后提取它们_Java_Android_Sockets_Io_Bytearray - Fatal编程技术网

Java 如何聚合两个字符串和一个列表<;字节[]>;转换为单个字节[],然后提取它们

Java 如何聚合两个字符串和一个列表<;字节[]>;转换为单个字节[],然后提取它们,java,android,sockets,io,bytearray,Java,Android,Sockets,Io,Bytearray,我需要将2个字符串和一个列表聚合成一个字节[],以便通过网络发送(使用一个具有函数send(byte[])的特殊库) 然后,在另一端,我需要取回3个不同的对象 我已经做了一个丑陋的实现,但它非常缓慢。基本上,我所做的是 public byte[] myserializer(String dataA, String dataB, List<byte[]> info) { byte[] header = (dataA +";" + dataB + ";"

我需要将2个字符串和一个列表聚合成一个字节[],以便通过网络发送(使用一个具有函数send(byte[])的特殊库)

然后,在另一端,我需要取回3个不同的对象

我已经做了一个丑陋的实现,但它非常缓慢。基本上,我所做的是

        public byte[] myserializer(String dataA, String dataB, List<byte[]> info) {

        byte[] header = (dataA +";" + dataB + ";").getBytes();

        int numOfBytes = 0;
        for (byte[] bs : info) {
            numOfBytes += bs.length;
        }

        ByteArrayOutputStream b = new ByteArrayOutputStream();
        ObjectOutputStream o;
        try {
            o = new ObjectOutputStream(b);
            o.writeObject(info);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        byte[] data = b.toByteArray();

        int length = header.length + data.length;
        byte[] headerLength = (new Integer(header.length)).toString()
                .getBytes();
        byte[] pattern = ";".getBytes();
        int finalLength = headerLength.length + pattern.length + length;

        byte[] total = new byte[finalLength];enter code here
        total = // Copy headerLength, header and total into byte[] total

        return return;
(-------------------------------------------------------------)(-------------------------------------) 标题长度;数据A;数据B;序列化列表对象

然后,在接收端,我做了相反的过程,这就是“全部”。这是可行的,但它是非常低效和丑陋的

建议?最佳实践?想法

哦……还有一点需要注意:这也必须适用于J2SE和Android


非常感谢advanced!!

将其全部写入一个
ByteArrayOutputStream
,并在其周围添加一个ObjectOutputStream来序列化字符串和列表,然后调用将BAO转换为byte[]数组的方法。在另一端,执行相反的操作

或者定义一个可序列化的对象,该对象包含
{String,String,List}
元组,只需使用
ObjectOutputStream
对其进行序列化,然后使用
ObjectInputStream
对其进行反序列化。这要简单得多


或者只发送三次。TCP是一个字节流,消息之间没有边界,字节都是按顺序到达的。如果要保留对网络的写入,请插入一个
缓冲输出流
,并在写入
列表后刷新它

将其全部写入
ByteArrayOutputStream
,对象为tputStream围绕它来序列化字符串和列表,然后调用将BAO转换为byte[]数组的方法。在另一端,执行相反的操作

或者定义一个可序列化的对象,该对象包含
{String,String,List}
元组,只需使用
ObjectOutputStream
对其进行序列化,然后使用
ObjectInputStream
对其进行反序列化。这要简单得多


或者只做三次发送。TCP是一个字节流,消息之间没有边界,字节都是按顺序到达的。如果您想保留对网络的写入,请插入一个
缓冲输出流
,并在写入
列表

后刷新它。下面是一个简单的方法,用于序列化字节数组和数据请注意,该方法只接受一个
List
类型的参数,并且由于您的参数
dataA
dataB
属于
String
类型,因此您可以简单地假设前两个
字节[]
列表中的元素就是这两个参数。我相信这比通过
ObjectOutputStream
进行对象序列化要快得多,并且在另一端反序列化也会更快

public class ByteListSerializer {
static private final int INT_SIZE = Integer.SIZE / 8;

    static public void main(String...args) {
        ByteListSerializer bls = new ByteListSerializer();

        // ============== variable declaration =================
        String dataA = "hello";
        String dataB = "world";
        List<byte[]> info = new ArrayList<byte[]>();
        info.add(new byte[] {'s','o','m','e'});
        info.add(new byte[] {'d','a','t','a'});
        // ============= end variable declaration ==============

        // ======== serialization =========
        info.add(0, dataA.getBytes());
        info.add(1, dataB.getBytes());
        byte[] result = bls.dataSerializer(info);

        System.out.println(Arrays.toString(result));

        // ======== deserialization ========
        List<byte[]> back = bls.dataDeserializer(result);

        String backDataA = new String(back.get(0));
        String backDataB = new String(back.get(1));
        back.remove(0);
        back.remove(0);

        // ============ print end result ============
        System.out.println(backDataA);
        System.out.println(backDataB);
        for (byte[] b : back) {
            System.out.println(new String(b));
        }
    }

    public byte[] dataSerializer(List<byte[]> data) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteBuffer lenBuffer = ByteBuffer.allocate(4);

        try {
            for (byte[] d : data) {
                lenBuffer.putInt(0, d.length);
                out.write(lenBuffer.array());
                out.write(d);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // wrap this
        byte[] dataBuffer = new byte[out.size() + 4];
        lenBuffer.putInt(0, out.size());
        System.arraycopy(lenBuffer.array(), 0, dataBuffer, 0, 4);
        System.arraycopy(out.toByteArray(), 0, dataBuffer, 4, out.size());

        return dataBuffer;
    }

    public List<byte[]> dataDeserializer(byte[] data) {
        if (data.length < INT_SIZE) {
            throw new IllegalArgumentException("incomplete data");
        }

        ByteBuffer dataBuffer = ByteBuffer.wrap(data);
        int packetSize = dataBuffer.getInt();

        if (packetSize > data.length - INT_SIZE) {
            throw new IllegalArgumentException("incomplete data");
        }

        List<byte[]> dataList = new ArrayList<byte[]>();
        int len, pos = dataBuffer.position(), nextPos;

        while (dataBuffer.hasRemaining() && (packetSize > 0)) {
            len = dataBuffer.getInt();
            pos += INT_SIZE;
            nextPos = pos + len;
            dataList.add(Arrays.copyOfRange(data, pos, nextPos));

            dataBuffer.position(pos = nextPos);
            packetSize -= len;
        }

        return dataList;
    }
}
上面的示例将输出

[0, 0, 0, 34, 0, 0, 0, 5, 104, 101, 108, 108, 111, 0, 0, 0, 5, 119, 111, 114, 108, 100, 0, 0, 0, 4, 115, 111, 109, 101, 0, 0, 0, 4, 100, 97, 116, 97]
hello
world
some
data

注意帧格式由
字节[]构成
chunks因此,只要您知道chunks的顺序,您就可以对几乎任何数据集使用这些方法。

这里是一种简单的方法,可以序列化字节数组并在另一端对其进行反序列化。请注意,该方法只接受一个类型为
List
的参数,并且由于您的参数
dataA
 dataB
属于
String
类型,您可以简单地假设列表中的前两个
byte[]
元素就是这两个参数。我相信这比通过
ObjectOutputStream
进行对象序列化要快得多,并且在另一端反序列化也会更快

public class ByteListSerializer {
static private final int INT_SIZE = Integer.SIZE / 8;

    static public void main(String...args) {
        ByteListSerializer bls = new ByteListSerializer();

        // ============== variable declaration =================
        String dataA = "hello";
        String dataB = "world";
        List<byte[]> info = new ArrayList<byte[]>();
        info.add(new byte[] {'s','o','m','e'});
        info.add(new byte[] {'d','a','t','a'});
        // ============= end variable declaration ==============

        // ======== serialization =========
        info.add(0, dataA.getBytes());
        info.add(1, dataB.getBytes());
        byte[] result = bls.dataSerializer(info);

        System.out.println(Arrays.toString(result));

        // ======== deserialization ========
        List<byte[]> back = bls.dataDeserializer(result);

        String backDataA = new String(back.get(0));
        String backDataB = new String(back.get(1));
        back.remove(0);
        back.remove(0);

        // ============ print end result ============
        System.out.println(backDataA);
        System.out.println(backDataB);
        for (byte[] b : back) {
            System.out.println(new String(b));
        }
    }

    public byte[] dataSerializer(List<byte[]> data) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteBuffer lenBuffer = ByteBuffer.allocate(4);

        try {
            for (byte[] d : data) {
                lenBuffer.putInt(0, d.length);
                out.write(lenBuffer.array());
                out.write(d);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // wrap this
        byte[] dataBuffer = new byte[out.size() + 4];
        lenBuffer.putInt(0, out.size());
        System.arraycopy(lenBuffer.array(), 0, dataBuffer, 0, 4);
        System.arraycopy(out.toByteArray(), 0, dataBuffer, 4, out.size());

        return dataBuffer;
    }

    public List<byte[]> dataDeserializer(byte[] data) {
        if (data.length < INT_SIZE) {
            throw new IllegalArgumentException("incomplete data");
        }

        ByteBuffer dataBuffer = ByteBuffer.wrap(data);
        int packetSize = dataBuffer.getInt();

        if (packetSize > data.length - INT_SIZE) {
            throw new IllegalArgumentException("incomplete data");
        }

        List<byte[]> dataList = new ArrayList<byte[]>();
        int len, pos = dataBuffer.position(), nextPos;

        while (dataBuffer.hasRemaining() && (packetSize > 0)) {
            len = dataBuffer.getInt();
            pos += INT_SIZE;
            nextPos = pos + len;
            dataList.add(Arrays.copyOfRange(data, pos, nextPos));

            dataBuffer.position(pos = nextPos);
            packetSize -= len;
        }

        return dataList;
    }
}
上面的示例将输出

[0, 0, 0, 34, 0, 0, 0, 5, 104, 101, 108, 108, 111, 0, 0, 0, 5, 119, 111, 114, 108, 100, 0, 0, 0, 4, 115, 111, 109, 101, 0, 0, 0, 4, 100, 97, 116, 97]
hello
world
some
data

注意帧格式由
字节[]构成
chunks因此,只要您知道chunks的顺序,就可以对几乎任何数据集使用这些方法。

很可能,序列化是性能成本的一个重要部分。因此,您可能希望自己序列化列表。一个明显的问题是字节数组之间的分隔符。如果存在任何你知道的字节将不在数组中。否则,你必须使用某种转义。是的,这就是我试图做的,但它有点复杂。我不能对信息块使用任何分隔符,因为它可以是二进制数据。我在考虑将列表元素的数量及其长度作为标题的一部分添加进去……这样你就不需要delimiters。我尝试了这种方法,但最终以意大利面代码结束。我选择的答案是,它尝试这样做,但更简洁!可能,序列化是性能成本的一个重要部分。因此,您可能希望自己序列化列表。一个明显的问题是字节数组之间的分隔符。如果有,您可以简化此操作你知道的任何字节都不会在数组中。否则,你必须使用某种形式的转义。是的,这就是我试图做的,但它有点复杂。我不能对信息块使用任何分隔符,因为它可以是二进制数据。我在考虑添加列表元素的数量及其长度作为标题的一部分…这样你就不会eed定界符。我尝试了这种方法,但最终以意大利面代码结束。我选择的答案是,它尝试这样做,但更简洁!将参数包装在内部对象中会更灵活、更易于维护将参数包装在内部对象中会更灵活、更易于维护
DataOutputStream
DataInputStream
可以做得更“简单”。@EJP,我相信它会产生几乎相同的代码,因为
DataOutputStream
不“序列化”,而只是以字节形式输出数据(如我的示例中所示),在返回结果字节之前,您仍然必须预先设置4字节的帧长度。只是一个问题:ByteArrayOutputStream和ByteBuffer对象的in/efficient有多高?假设我创建了