JNorr44
JNorr44

Reputation: 274

Converting a Map<String, Object> to a byte[] and back

Alright, so I have two methods that should work as far as I can tell which gets something called an ItemStack, and serializes it.

  1. The serialization is then entered into a ByteOutputStream and is turned into a byte[]. That byte[] is then turned into a byte, with a special separator set a bytes in between.
  2. Each of these bytes (there is originally an ItemStack[]) are entered into a byte[], and stored in a byte[][][].
  3. Later on, I try to retrieve the ItemStack[] from the byte[] by calling another method, which uses the special separator set of bytes to separate the byte[] into a byte and convert that to a Map<String, Object>, then into an ItemStack.

This all must be very confusing, as it is for me, so I will post what I currently have below (just the two methods). If any more is required, please let me know, and I can most-likely get it.

My problem is that this doesn't work. No errors or anything, but for some reason the data does not make it all the way through. If anyone has any solutions to this, please help. Maybe it is with the way I am splitting the data... or maybe I am cutting off or adding on bytes to what was a string or object.

private static byte[] contentsToBytes(Block block, ItemStack[] contents) throws IOException {
    byte[] bytes = new byte[] {block.getData()};
    byte[] dataSplitter = ITEMSTACKDATASPLITTER.getBytes("UTF-8");
    for (int i = 0; i < contents.length; i++) {
        Map<String, Object> serialized = contents[i].serialize();
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteOut);
        out.writeObject(serialized);
        byte[] serializedByteArray = byteOut.toByteArray();
        byte[] copyBytes = Arrays.copyOf(bytes, bytes.length + dataSplitter.length + serializedByteArray.length);
        for (int j = 0; j < dataSplitter.length; j++) {
            copyBytes[bytes.length + j] = dataSplitter[j];
        }
        for (int k = 0; k < serializedByteArray.length; k++) {
            copyBytes[bytes.length + dataSplitter.length + k - 1] = serializedByteArray[k];
        }
        bytes = copyBytes;
    }
    return bytes;
}    

private static ItemStack[] bytesToContents(byte[] bytes) throws IOException, ClassNotFoundException {
    ArrayList<ItemStack> stacks = new ArrayList<ItemStack>();
    byte[] dataSplitter = ITEMSTACKDATASPLITTER.getBytes("UTF-8");
    byte[] currentByteItemStack = new byte[1];
    boolean decompress = false;
    for (int i = 1; i < bytes.length; i++) {
        byte current = bytes[i];
        if (current == dataSplitter[0]) {
            byte[] dataSplitterTest = Arrays.copyOfRange(bytes, i, i - 1 + dataSplitter.length);
            boolean match = true;
            for (int j = 0; j < dataSplitter.length; j++) {
                if (dataSplitter[j] != dataSplitterTest[j]) {
                    match = false;
                    break;
                }
            }
            if (decompress && match) {
                ByteArrayInputStream byteIn = new ByteArrayInputStream(Arrays.copyOfRange(currentByteItemStack, 0, currentByteItemStack.length - 2));
                ObjectInputStream in = new ObjectInputStream(byteIn);
                @SuppressWarnings("unchecked") Map<String, Object> serialized = (Map<String, Object>) in.readObject();
                stacks.add(ItemStack.deserialize(serialized));
            }
            i += dataSplitter.length - 1;
            decompress = match;
        }
        if (decompress) {
            currentByteItemStack = Arrays.copyOf(currentByteItemStack, currentByteItemStack.length + 1);
            currentByteItemStack[i - 1] = current;
        }
    }
    return stacks.toArray(new ItemStack[stacks.size()]);
}    

Upvotes: 1

Views: 15911

Answers (1)

greedybuddha
greedybuddha

Reputation: 7507

So it sounds like you are going through great lengths to write your own Serialization, but java already has great serialization built in.

If it's because these objects you are trying to Serialize don't implement Serializable, then make a temporary wrapper class that you make that can be serialized, then you can use the default Serialization.

Example

public class MyItemStack implements Externalizable{
    private static final long serialVersionUID = 1L;
    ItemStack itemStack;
    MyItemStack(ItemStack itemStack){
        this.itemStack = itemStack;
    }
    @Override
    public void readExternal(ObjectInput arg0) throws IOException, ClassNotFoundException {
        ...
    }

    @Override
    public void writeExternal(ObjectOutput arg0) throws IOException {
        ...
    }
}

Now you just have to override those methods to store what an ItemStack or Block really means (usually as primitives)

Serialization afterwards should be fairly simple, something like this.

FileOutputStream fos = new FileOutputStream("myfile");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(myHashMap);
oos.close();

FileInputStream fis = new FileInputStream("myfile");
ObjectInputStream ois = new ObjectInputStream(fis);
Map<String,MyItemStack> myMap = (Map<String,MyItemStack>) ois.readObject();
ois.close();

Upvotes: 5

Related Questions