Add a value to a function of treeMap without losing old data - java

I have a Map:
Map<String, DistributorAdd> map= new TreeMap<String, DistributorAdd>();
and I save it in a file.txt
FileOutputStream fos = new FileOutputStream("Distrib.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(map);
oos.close();
The problem is that Distributor who was yesterday like:
public DistributorAdd(String distributor, String
emailAdress, String name, String speciality){...}
Will be tomorrow like this:
public void ajouter(String Distributor, String EmailAdress,
String Name, String Phone, String Image) {..}
My coworker already placed a lot of info in her Distrib.txt so what I want is to be able to put a new String in the Map without destroying it.
I would like to keep Distrib.txt and my DistributorAdd function is there any easy step I could do to do that?
The kind of error I get is:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Distrib.txt"));
VendorA = (DistributorAdd) ois.readObject();
Error:
IOException : table.java => table()java.io.StreamCorruptedException: invalid stream header: ACED0573
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:780)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:277)
at car.Table.<init>(Table.java:185)
at car.Table.main(Table.java:837)
If you have any question or any more information that I need to give I will be happy to do it.

Please note following things about serialization:
1)It has to be used very judiciously.
2)When we serialise a class , it is like we are exporting its API in terms of
instance variables.
3)Always explicitely declare SerialVersionUID in your serializable class,if we
don't it will be automatically calculated by JVM based on internal structure of your class
(instance vars,public methods etc.) so changing internal strcture of class
chnages this SerialVersionUID.
Hence , If we serailise a class in one version and then deserialise it in another version
(by version change I mean we are changing some internal structure of serializable
object) , version incompatibility is bound to happen.
I am not sure what exactly may have caused for your code to fail since I don't know
what chnages are you doing in your Serializable class.
But I think you should consider point 3 once

Related

How to read File and convert it to Hashmap? [duplicate]

I have a data structure that I would like to be able to write to a file before closing the program, and then read from the file to re-populate the structure the next time the application starts.
My structure is HashMap<String, Object>. The Object is pretty simple; For member variables it has a String, and two small native arrays of type Boolean. This is a real simple application, and I wouldn't expect more than 10-15 <key,value> pairs at one time.
I have been experimenting (unsuccessfully) with Object input/output streams. Do I need to make the Object class Serializable?
Can you give me any suggestions on the best way to do this? I just need a push in the right direction. Thanks!
EDIT: Well I feel dumb still, I was writing from one map and reading into another map, and then comparing them to check my results. Apparently I was comparing them wrong. Sigh.
If you aren't concerned about Object particularly , you just need key value pair of String,String then I would suggest you to go for java.util.Properties. otherwise here you go
Map map = new HashMap();
map.put("1",new Integer(1));
map.put("2",new Integer(2));
map.put("3",new Integer(3));
FileOutputStream fos = new FileOutputStream("map.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(map);
oos.close();
FileInputStream fis = new FileInputStream("map.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
Map anotherMap = (Map) ois.readObject();
ois.close();
System.out.println(anotherMap);
Map m = new HashMap();
// let's use untyped and autoboxing just for example
m.put("One",1);
m.put("Two",2);
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("foo.ser")
);
oos.writeObject(m);
oos.flush();
oos.close();
Yes, your objects will need to implement Serializable in order to be serialized by the default Java mechanism. HashMap and String already implement this interface and thus can be serialized successfully.
Take a look at Sun's own Serialization tutorial - it's quite short and I think should cover everything you need for your simple case. (You should just be able to serialise the Map object to the stream, and then read it back in on subsequent runs).
If you do run into problems, try serializing a simple HashMap<String, String> with some dummy values. If this succeeds, you'll know that the problem lies (somehow) with your own class' serializability; alternatively, if this doesn't work you can focus on the basic structure before throwing your own class into the mix.
Post back if you have any more specific problems that you can't figure out on your own.
Yes, if you want to write an object to the file system, that object must implement Serializeable. Here is a tutorial that should help you out.
Don't bother with making it Serializable until you understand more about what that's used for. You want to look at FileWriter and google "java file io" A good way to write this data is as CSV.
eg.
key1,key2,key3
valuea1,valuea2,valuea3
valueb1,valueb2,valueb3
Hope this helps.
SERIALIZE A HASHMAP:
This code is working fine , I have implemented and used in my app. Plz make ur functions accordingly for saving map and retrieving map.
Imp thing is, you need to make confirm that the objects you are putting as value in map must be serializable , means they should implement serailizbele interface. ex.
Map<.String,String> hashmap=new HashMap<.String,String>().. here in this line ...map and string both are implictly serializable , so we dont need to implement serializble for these explicitly but if you put your own object that must be serializable.
public static void main(String arr[])
{
Map<String,String> hashmap=new HashMap<String,String>();
hashmap.put("key1","value1");
hashmap.put("key2","value2");
hashmap.put("key3","value3");
hashmap.put("key4","value4");
FileOutputStream fos;
try {
fos = new FileOutputStream("c://list.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(hashmap);
oos.close();
FileInputStream fis = new FileInputStream("c://list.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
Map<String,String> anotherList = (Map<String,String>) ois.readObject();
ois.close();
System.out.println(anotherList);
} catch (FileNotFoundException e) {e.printStackTrace();
} catch (IOException e) {e.printStackTrace();
} catch (ClassNotFoundException e) {e.printStackTrace();
}
}
I'd advise against using Serializable; it is much harder to do properly than it first seems. It would seem that simply adding implements Serializable is all you need to do. But in fact this adds many restrictions on your code that are difficult to deal with in practical software development (rather than in school). To see just how horrible these restrictions are, see the book Effective Java (second edition) by Bloch.

NotSerializableException with java.awt.geom.Area

I'm creating a game where all locations of 'blocks' are stored in the variable block_area - an object of class Area. My game has been running correctly for a week now, and I've decided to implement a save and load feature where I save block_area to a file Drifter, with this as my code:
Area block_area; // Later initialized
void saveArea()
{
try
{
FileOutputStream fos = new FileOutputStream(savefile);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(block_area);
oos.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
void loadArea()
{
try
{
FileInputStream fis = new FileInputStream(savefile);
ObjectInputStream ois = new ObjectInputStream(fis);
block_area = (Area)ois.readObject();
ois.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
However, this is my very first time writing and reading an OBJECT to a file, so I don't know much about it. When I try to save the object to the file, it gives me this error:
java.io.NotSerializableException: java.awt.geom.Area
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at Drifter.saveArea(Drifter.java:58)
at Drifter.keyPressed(Drifter.java:315)
...
If anyone can tell me how I can go about writing and reading an object with a file, the help will be greatly appreciated.
TL;DR How do I write the contents of an Area object to a file and read it?
ALSO I have a few follow-up questions:
Is ObjectInputStream the best course of action here? I have seen a few answers where people recommend using XML, and JSON, but I can never find the time to learn about them, and would prefer to stick to a pure Java method (without any third party tools)
Is there any other method of saving an object's information to an external source that I can use instead of file handling?
EDIT - I should also mention that my class implements Serializable
The exception is pretty self explanatory NotSerializableException: java.awt.geom.Area . Any object that you want to serialize must implement the Serializable interface. java,awt.geom.Area does not. Any attributes of that class must also implement Serializable, be a primitive, or be defined as transient.
I'd suggest either Figuring out a way to read Area into an object that does implement Serializable. When you read it back out, you can construct a new Area object. This is probably what the JSON/XML method mentioned in the comments is doing. The added benefit of a human readable storage format is that you can edit it in a text editor. You won't be able to do that with the binary output of a serialized object`.

Add item to serialized list in a file

I have an ArrayList of a Serializable, which I can serialize then save and load it from a file. But what if I want to add an object to the arraylist, without loading the whole list, then saving the whole thing again? I don't feel like loading the whole list, then adding an object to it and then save it again, as it would impact my performance.
These are the two method I've made for saving and loading the file. The Deck class of course implements Serializable.
public static List<Deck> loadDeckDatabase() throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream("decks");
ObjectInputStream ois = new ObjectInputStream(fis);
List decList = (List) ois.readObject();
ois.close();
return decList;
}
public static void saveDeckDatabase(List<Deck> decks) throws IOException, ClassNotFoundException {
FileOutputStream fos = new FileOutputStream("decks");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(decks);
oos.close();
}
I hope someone can help me. Thanks!
Either:
You have to load and save, as you don't know how the Deck is serialized.
You can to write your own serialization so you actually know how to append.
See also here:
https://stackoverflow.com/a/7290812/461499
Why don't you just use SQLite database? It is light, local (stored just in file) database supported by Java. The way you are using it is same that using common database.
Look at the tutorial here: http://www.tutorialspoint.com/sqlite/sqlite_java.htm
If you don't want to use the database I see two ways to dealt with you problem:
Keep every array object in other file and keep a files counter in some place - which is not very elegant solution and I guess it will increase I/O operations count
Serialize your structure to JSON and write your own method to add element. Since JSON's structure is very simple it seems to be quite easy to just add new element with simple file and string operations

What is the proper way to write/read a file with different IO streams

I have a file that contains bytes, chars, and an object, all of which need to be written then read. What would be the best way to utilize Java's different IO streams for writing and reading these data types? More specifically, is there a proper way to add delimiters and recognize those delimiters, then triggering what stream should be used? I believe I need some clarification on using multiple streams in the same file, something I have never studied before. A thorough explanation would be a sufficient answer. Thanks!
As EJP already suggested, use ObjectOutputStream and ObjectInputStream an0d wrap your other elements as an object(s). I'm giving as an answer so I could show an example (it's hard to do it in comment) EJP - if you want to embed it in your question, please do and I'll delete the answer.
class MyWrapedData implements serializeable{
private String string1;
private String string2;
private char char1;
// constructors
// getters setters
}
Write to file:
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName));
out.writeObject(myWrappedDataInstance);
out.flush();
Read from file
ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName));
Object obj = in.readObject();
MyWrapedData wraped = null;
if ((obj != null) && (obj instanceof MyWrappedData))
wraped = (MyWrapedData)obj;
// get the specific elements from the wraped object
see very clear example here: Read and Write
Redesign the file. There is no sensible way of implementing it as presently designed. For example the object presupposes an ObjectOutputStream, which has a header - where's that going to go? And how are you going to know where to switch from bytes to chars?
I would probably use an ObjectOutputStream for the whole thing and write everything as objects. Then Serialization solves all those problems for you. After all you don't actually care what's in the file, only how to read and write it.
Can you change the structure of the file? It is unclear because the first sentence of your question contradicts being able to add delineators. If you can change the file structure you could output the different data types into separate files. I would consider this the 'proper' way to delineate the data streams.
If you are stuck with the file the way it is then you will need to write an interface to the file's structure which in practice is a shopping list of read operations and a lot of exception handling. A hackish way to program because it will require a hex editor and a lot of trial and error but it works in certain cases.
Why not write the file as XML, possibly with a nice simple library like XSTream. If you are concerned about space, wrap it in gzip compression.
If you have control over the file format, and it's not an exceptionally large file (i.e. < 1 GiB), have you thought about using Google's Protocol Buffers?
They generate code that parses (and serializes) file/byte[] content. Protocol buffers use a tagging approach on every value that includes (1) field number and (2) a type, so they have nice properties such as forward/backward compatability with optional fields etc. They are fairly well optimized for both speed and file size, adding only ~2 bytes of overhead for a short byte[], with ~2-4 additional bytes to encode the length on larger byte[] fields (VarInt encoded lengths).
This could be overkill, but if you have a bunch of different fields & types, protobuf is really helpful. See: http://code.google.com/p/protobuf/.
An alternative is Thrift by Facebook, with support for a few more languages although possibly less use in the wild last I checked.
If the structure of your file is not fixed, consider using a wrapper per type. First you need to create the interface of your wrapper classes….
interface MyWrapper extends Serializable {
void accept(MyWrapperVisitor visitor);
}
Then you create the MyWrapperVisitor interface…
interface MyWrapperVisitor {
void visit(MyString wrapper);
void visit(MyChar wrapper);
void visit(MyLong wrapper);
void visit(MyCustomObject wrapper);
}
Then you create your wrapper classes…
class MyString implements MyWrapper {
public final String value;
public MyString(String value) {
super();
this.value = value;
}
#Override
public void accept(MyWrapperVisitor visitor) {
visitor.visit(this);
}
}
.
.
.
And finally you read your objects…
final InputStream in = new FileInputStream(myfile);
final ObjectInputStream objIn = new ObjectInputStream(in);
final MyWrapperVisitor visitor = new MyWrapperVisitor() {
#Override
public void visit(MyString wrapper) {
//your logic here
}
.
.
.
};
//loop over all your objects here
final MyWrapper wrapper = (MyWrapper) objIn.readObject();
wrapper.accept(visitor);

Java Deserialization of java.lang.Integer - Exception

Recieved the following exception when deserializing a HashMap<String, Integer>:
java.io.InvalidClassException: java.lang.Integer; local class incompatible: stream classdesc serialVersionUID = 1360826667802527544, local class serialVersionUID = 1360826667806852920
Serialized and deserialized on the same machine, with the same JRE. JDK 1.6.0_12
From looking at the JDK source, 1360826667806852920 is the correct serialVersionUID for Integer. I wasn't able to find any classes in the JDK with the serialVersionUID 1360826667802527544.
Interestingly, searching for 1360826667802527544 on Google turned up a few other people with this problem, notably this thread on Sun's forums. The problem there was that the person was storing bytes in a String, and the serialized data was getting mangled. Since you're getting the same serialVersionUID it seems very likely that you're running into a similar problem.
Never store bytes in a String. Use a byte array or a class designed to hold bytes, not chars.
That shouldn't happen. Note that the IDs differ only in the last few digits; the second one ist the one I see in my JDK sources.
My guess is that the serialized stream got corrupted somehow.
check the source code for Integer, here is what I have for Integer in several verions of java:
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = 1360826667806852920L;
So I'd say the problem comes from a class of yours that you changed between serialization and deserialization and that has no specific serialVersionUID...
Maybe you should look at this, same problem description and it looks like wrong serialization / deserialization code....
I faced the same issue and it is because when we are trying to store Integer object to String, the character encoding is getting messed up and while deserialization the serialVersionUID read is wrong. That's the root cause of this error.
To avoid this error use Base64 encoding before storing it to String.
see this answer and the problem resolved for me.
/** Read the object from Base64 string. */
private static Object fromString( String str ) throws IOException, ClassNotFoundException {
byte [] data = Base64.getDecoder().decode(str);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
Object o = ois.readObject();
ois.close();
return o;
}
/** Write the object to a Base64 string. */
private static String toString( Serializable o ) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream( baos );
oos.writeObject( o );
oos.close();
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
I've run into the same issue on a compiled jasperreport.
The packed ear on the server was corrupted due to the filtering of the ant build. As a result, the original jasperreport file with the one on the ear had some differences.
I've modified the ant build to copy only the file (instead of filtering) and not filter the

Categories

Resources