Reputation: 274
Alright, so I have two methods that should work as far as I can tell which gets something called an ItemStack
, and serializes it.
ByteOutputStream
and is turned into a byte[]
. That byte[]
is then turned into a byte
, with a special separator set a bytes in between. ItemStack[]
) are entered into a byte[]
, and stored in a byte[][][]
.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
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