Как объединить две строки и списокв один байт [], а затем извлечь их - PullRequest
0 голосов
/ 24 октября 2011

Мне нужно объединить 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;

По сути, я создаю вид рамки, которая выглядит следующим образом

      HEADER                    INFO

(---------------------------------------------- -) (----------------------------------) HEADER_LENGHT; DATA_A; Данные; SERIALIZED_LIST_OBJECT

Затем, на стороне получателя, я делаю обратный процесс, и это «все». Это работает, но ДОВОЛЬНО неэффективно и безобразно.

Предложения? Лучшие практики? Идеи?

Ох ... еще одно замечание: это должно работать и для J2SE, и для Android

Большое спасибо заранее!

Ответы [ 2 ]

2 голосов
/ 24 октября 2011

Запишите все это в ByteArrayOutputStream, с объектом ObjectOutputStream вокруг него, чтобы сериализовать строки и список, а затем вызовите метод, который превращает BAOS в массив byte [].На другом конце сделайте обратное.

Или определите сериализуемый объект, содержащий кортеж {String, String, List}, и просто сериализуйте его с помощью ObjectOutputStream, и десериализовайте его с помощью ObjectInputStream.Гораздо проще.

Или просто три посылки.TCP - это поток байтов, между сообщениями нет границ, все байты поступают последовательно.Если вы хотите сохранить записи в сети, вставьте BufferedOutputStream и очистите его после записи List.

1 голос
/ 24 октября 2011

Вот упрощенный метод сериализации массива байтов и десериализации его на другой стороне. Обратите внимание, что метод принимает только один аргумент типа List<byte[]>, и поскольку ваши аргументы 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;
    }
}

Рамка построена как

     - 4 bytes: the total bytes to read (frame size = [nnnn] + 4 bytes header)
    |      - 4 bytes: the first chunk size in bytes
    |     |          - x bytes: the first chunk data
    |     |         |          
    |     |         |           - 4 bytes: the n chunk size in byte
    |     |         |          |         - x bytes: the n chunk data
    |     |         |          |        |
    |     |         |          |        |
[nnnn][iiii][dddd....][...][iiii][dddd...]

В приведенном выше примере будет выведено

[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

Обратите внимание , что формат кадра сформирован из byte[] чанков, поэтому, если вы знаете порядок чанков, вы можете использовать эти методы практически с любым набором данных.

...