i am developing a small application in Java. At certain point i need to save the object of my custom class to a text file for this i override toString() method in my custom class and then use ObjectOutputStream class to save object of my custom class to text file. Now everything works fine i.e the text file contains the text as expected. Following three lines contain major code for that
ObjectOutputStream outputStream = null;
outputStream = new ObjectOutputStream(new FileOutputStream(filename));
outputStream.writeObject(person);//person is the instance of my custom class
Now, how do i add some static data to my file along with the object data
outputStream = new ObjectOutputStream(new FileOutputStream(filename));
outputStream.WhatFunctoinToUse("some static text");//What function i use to add static text??
outputStream.writeObject(person);//person is the instance of my custom class
Short answer: You don't.
ObjectOutputStream is not meant to be used in that fashion. It outputs a Serializable object in a format specified by the API. This is not always a good idea, i.e. it is easy to break compatibility in future releases.
Although the format outputted looks readable, it contains a lot of non-printable characters, that adding some static text to probably would break the serialization.
What you are looking for is either:
a) A clear-text serialization such as JSON or XML (Try http://simple.sourceforge.net/, it's really simple)
b) A text file besides your serialized object.
You should NOT try to extend the functionality of the ObjectOutputStream unless you have a very very good reason for it, and it does not seem you have.
If you want to append a primitive type value to be flattened with an Object, pass your ObjectOutputStream to PrintStream to enable you append a new line which will effect hold the static value as require.
See below for both Reading and writing.
//Writting
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("person.out"));
outputStream.writeObject(person);
PrintStream pst = new PrintStream(outputStream);
pst.append("Some static Value");
outputStream.flush();
outputStream.close();
pst.close();
// Reading
ObjectInputStream in = new ObjectInputStream(new FileInputStream("person.out"));
Perrson person=(Person) in.readObject();
String staticText =in.readLine();
in.close();
Hope you realise that by making use of ObjectOutputStream and writing person to it, you're in essence serializing the person object.
Related
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.
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`.
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
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);
when I write a new text file in Java, I get these characters at the beginning of the file:
¨Ìt
This is the code:
public static void writeMAP(String filename, Object object) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename));
oos.writeObject(object);
oos.close();
}
thanks
Writer output = null;
String text = "Www.criandcric.com. is my site";
File file = new File("write.txt");
output = new BufferedWriter(new FileWriter(file));
output.write(text);
output.close();
I hope with this You can get an idea how to do that.
ObjectOutputStreams are not meant for writing "text files." They are used specifically for writing an intermediate representation of Java objects out to disk. This process is known as serialization.
You most likely want to use a Writer, which is more useful for making human-readable text files. In particular, you should look at FileWriter and/or PrintWriter.
When using ObjectOutputStream you make binary serialization of your object. You aren't supposed to view the file as a "text file" at all.
If you want to serialize your object in a human-readable way, use java.beans.XMLEncoder. Read the linked docs on how to use it in a similar way to ObjectOutputStream. It produces XML.
You're not writing text to the file, you're writing objects to it, which means you get a stream header, type information and internal structure. To write text, use a Writer:
Writer w = new OutputStreamWriter(new FileOutputStream(filename), encoding);