Ich plane, ByteArrayOutputStream verwenden, um Objekte in Byte-Array zu schreiben, dann schreibe das Byte-Array in eine Datei. Ich behalte die Position jedes Objekts. Dann lese ich mit FileInputStream.getChannel(). Position() aus der Datei, um die Position zu verschieben, und rufe ObjectInputStream.readObject() auf.Java-Serialisierung Random Access, eine sehr seltsame Sache!
Hier ist mein Testcode:
public static void main(String[] args) {
try {
HashBucketTest bucket1 = new HashBucketTest();
bucket1.putAddress("0", 30);
HashBucketTest bucket2 = new HashBucketTest(); // bucket2 key is the same as bucket3
bucket2.putAddress("22313", 40);
HashBucketTest bucket3 = new HashBucketTest();
bucket3.putAddress("22313", 50);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oops = new ObjectOutputStream(baos);
FileOutputStream fout = new FileOutputStream("objects.txt");
BufferedOutputStream bs = new BufferedOutputStream(fout);
int position1 = baos.size(); // the first object position
bs.write(baos.toByteArray()); // write head
baos.reset();
oops.writeObject(bucket1); // write the first object to byte array
int position2 = position1 + baos.size(); // the second object position
bs.write(baos.toByteArray()); // write first object to file
baos.reset();
oops.writeObject(bucket2); // write the second object to byte array
int position3 = position2 + baos.size(); // the third object position
bs.write(baos.toByteArray()); // write the second object to file
baos.reset();
oops.writeObject(bucket3); // write the third object to byte array
int position4 = position3 + baos.size(); // the fourth object position
bs.write(baos.toByteArray()); // write the third object to file
baos.reset();
bs.flush();
bs.close();
fout.flush();
fout.close();
// read according to the position x
HashBucketTest readCase1 = null;
HashBucketTest readCase2 = null;
HashBucketTest readCase3 = null;
FileInputStream fis = new FileInputStream("objects.txt");
ObjectInputStream ois = new ObjectInputStream(
fis);
// success case
readCase1 = (HashBucketTest) ois.readObject(); // read the first object, success
fis.getChannel().position(position2);
readCase2 = (HashBucketTest) ois.readObject(); // read the second object, success
fis.getChannel().position(position3);
readCase3 = (HashBucketTest) ois.readObject(); // read the third object, success
// failed case!!!!
//readCase1 = (HashBucketTest) ois.readObject(); // read the first object, success
//fis.getChannel().position(position3);
//readCase3 = (HashBucketTest) ois.readObject(); // read the third object, failed!!
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static class HashBucketTest implements Serializable {
private static final long serialVersionUID = 3610182543890121796L;
Map<String, Integer> values = null; // need to write to disk
public HashBucketTest() {
values = new TreeMap<String, Integer>();
}
public void putAddress(String key, int number) {
values.put(key, number);
}
}
Mein Problem ist, wenn der Schlüssel von "bucket2" ist das gleiche wie "bucket3" ("22313" in diesem Fall). Ich kann nicht lesen bucket3 skippet bucket2
java.io.StreamCorruptedException: invalid handle value: 007E000C
at java.io.ObjectInputStream.readHandle(ObjectInputStream.java:1456)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1331)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at java.util.TreeMap.buildFromSorted(TreeMap.java:2563)
at java.util.TreeMap.buildFromSorted(TreeMap.java:2504)
at java.util.TreeMap.readObject(TreeMap.java:2450)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1896)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.alibaba.middleware.benchmark.Test.main(Test.java:146)
Aber wenn der Schlüssel anders ist, kann ich dies erfolgreich tun. Es scheint, dass sich der Schlüssel von bucket3 auf die Bucket2's bezieht. das ist sehr seltsam. Und auf jeden Fall ist das sequentielle Lesen in Ordnung, aber ich möchte kein sequentielles Lesen.
Vielen Dank für die Antwort. Was sollte ich verwenden, um den Anwendungsfall zu erreichen? Ich muss einige Objekte in Dateien schreiben und sie zufällig lesen. –
Es ist schwer zu sagen, ohne mehr über die Daten zu wissen, aber vielleicht möchten Sie Ihr eigenes Format mit fester Länge. –
Mein Objekt ist etwas wie der 'HashBucketTest', aber die Map ist' Map >> ', deren Größe sehr groß sein kann. –