Edit for clarification:
Why this does not appear to be a normal null reference is the fact that I have already used this code in another form and have had no issue there. I could manually delete the file from my device and the file will just be replaced later. This should be handled by my try/catch statement where if the file does not exist it will initialize a new object for me.
Furthermore when I get the error in android studio upon running it, the error points directly at the
FileInputStream fis = openFileInput(FILENAME);
Another thing to note is that when I add an item to the object that I am trying to pass into gson I have no issues. The object is created and I have no issue whatsoever adding items to it.
Furthermore as context, I have these two functions in an object class that manages my data for me. I create a single one of these objects as a DataManager and use these functions to save/load (among others) an object that contains all of my data within itself.
When I was putting the class together I had to add that the object class
extends Activity
Because I was getting the fileoutput and fileinput as red functions beforehand. However this seems very sketchy to me (and perhaps explains exactly why I am seeing this error...?)
Original before edit:
In my Android Studio application I've been trying my best to utilize gson and at present I am attempting to save a single object containing multiple attributes using gson.
However I just successfully managed to use this same gson code to put an ArrayList into a file. I could delete that file myself and everything would work just fine. However I am now trying to place an entire object in.
The error is: "java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.FileOutputStream android.content.Context.openFileOutput(java.lang.String, int)' on a null object reference"
The code looks like the following:
public void loadFromFile() {
try {
FileInputStream fis = openFileInput(FILENAME);
BufferedReader in = new BufferedReader(new InputStreamReader(fis));
Gson gson = new Gson();
// https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/Gson.html, 2015-09-23
Type objectType = new TypeToken<StatisticsRecordObject>() {}.getType();
recordObject = gson.fromJson(in, objectType);
} catch (FileNotFoundException e) {
recordObject = new StatisticsRecordObject();
}
}
public void saveInFile() {
try {
FileOutputStream fos = openFileOutput(FILENAME, 0);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fos));
Gson gson = new Gson();
gson.toJson(recordObject, out);
out.flush(); //same as fflush as before. Buffer must go. FLUSH AFTER WRITING.
fos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
recordObject = new StatisticsRecordObject();
} catch (IOException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
I think the NullpointerException says that context object that you call "openFileForOutput" is null
http://developer.android.com/reference/android/content/Context.html#openFileOutput(java.lang.String, int)
You should probably pass in a context to the method and make sure that the context is proper initialised.
Related
I might be trying to do this the hard way so let me know if there is a better solution.
I am making a simple text game in Java which you select your actions by a GUI. I have a couple of classes I am trying to serialize one being the player and another being an NPC. Is there an easy way to serialize more then one object (player and NPC) into the same file? I can serialize one object and load it back into the game.
Am I going about this the wrong way? Is there a simpler way of trying to save the game state?
If I have a class that creates multiple objects and I serialize that class, will the objects it created be serialized as well?
Thanks
An alternate approach to writing objects sequentially is to store them in a collection (e.g. a HashMap), since collections can be serialized. This may make it a little easier to manage upon retrieval, especially if you have many objects to serialize/deserialize. The following code demonstrates this:
String first = "first";
String second = "second";
HashMap<String, Object> saved = new HashMap<String, Object>();
saved.put("A", first);
saved.put("B", second);
try {
FileOutputStream fos = new FileOutputStream("test.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(saved);
oos.flush();
oos.close();
fos.close();
FileInputStream fis = new FileInputStream("test.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
HashMap<String,Object> retreived = (HashMap<String,Object>)ois.readObject();
fis.close();
System.out.println(retreived.get("A"));
System.out.println(retreived.get("B"));
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
Running this should result in:
first
second
Just call writeObject() as many times with as many different objects as you need, and conversely call readObject() ditto.
Hard to believe you haven't already tried it.
I am trying to write an object into hdfs .
Split currentsplit = new Split();
Path p = new Path("C45/mysavedobject");
ObjectOutputStream oos = new ObjectOutputStream(fs.create(p));
oos.writeObject(currentsplit);
oos.close();
But I am not able to get the exact object value.
Path p = new Path("C45/mysavedobject");
Split curntsplit = null;
ObjectInputStream ois = new ObjectInputStream(fs.open(p));
try {
curntsplit = (Split) ois.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ois.close();
Showing duplicate objects value.
In driver i am getting :
objjjjjjj in driver pck.Split#14da173c
After writing the object into file and reading back within driver itself I am getting an alternate object value.
objjjjjj in mysavedobject pck.Split#62eade0
I want the driver object along my Mapper code.
Why is it so?
Your custom Split object (pck.Split) doesn't have a toString method defined so what you're seeing is the class name followed by an address in memory (as Java has no otherway to display to you the string value of that object).
Simply add a toString method implementation to your custom Split class and rerun - now you should be able to confirm whether the written and read object has the same contents.
Currently, I'm using gson, to perform serialization on Objects. It works pretty fine in single platform (Windows).
However, if I were gonna to share the json file across different platforms (Windows, Linux, Mac, Android), do I need to specific type of encoding (UTF-8) being used? (There will be foreign language characters in json file)? Or, the default encoding used by BufferedWriter/BufferedReader will be same across all platforms?
public static boolean write(A a, File file) {
final Gson gson = new Gson();
String string = gson.toJson(a);
try {
//If the constructor throws an exception, the finally block will NOT execute
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
try {
writer.write(string);
} finally {
//no need to check for null
//any exceptions thrown here will be caught by
//the outer catch block
writer.close();
}
} catch (IOException ex){
return false;
}
return true;
}
public static A load(File file) {
// Copy n paste from newInstance.
final Gson gson = new Gson();
try {
//If the constructor throws an exception, the finally block will NOT execute
BufferedReader reader = new BufferedReader(new FileReader(file));
try {
return gson.fromJson(reader, A.class);
} finally {
//no need to check for null
//any exceptions thrown here will be caught by
//the outer catch block
reader.close();
}
} catch (IOException ex){
}
return null;
}
Just to add to it, FileReader and FileWriter are platform specific. Prefer ObjectStreams instead. Again, my score does not permit me to put it as a comment:(
Hi I have an issue when trying to append new objects to the existing file..
Once the android app has been lunched again I want to get the existing file and add a new objects then read the objects from the existing file ... Actually, when I'm trying to read the object, the code will read only the first objects .. You can find below the code .. Could you please help ? Thanks
using the following method to write an objects :
public void saveObject(Person p, File f){
try
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f, true));
oos.writeObject(p);
oos.reset();
oos.flush();
oos.close();
}
catch(Exception ex)
{
Log.v("Serialization Save Error : ",ex.getMessage());
ex.printStackTrace();
}
}
Using the following method to read an objects :
public Object loadSerializedObject(File f)
{
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
try{
Object loadedObj = null;
while ((loadedObj = ois.readObject()) != null) {
Log.w(this.getClass().getName(), "ReadingObjects") ;
}
return objects;
}finally{
ois.close();
}
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
Unfortunately you can't create a new ObjectOutputStream every time you want to append to the stream and then read everything back with a single stream. The constructor adds headers to the underlying stream before you start writing objects. You are probably seeing the java.io.StreamCorruptedException: invalid type code: AC exception, that's because the first header is 0xAC.
I don't know how many objects you are dealing with, but one option might be to read all your objects and then rewriting them all using a single ObjectOutputStream. That can get pricy if there are lots of objects. Alternatively, you might want to consider managing the serialization yourself manually through Externalizable. It can get painful though.
I serialize an object and save it as a file on my HDD. When I'm reading it, in only some occasions it throws EOFException. After couple of hours debugging I am not able to find a problem.
Here is my code:
public void serialize(MyClass myClass,String path) {
FileOutputStream foStream = null;
ObjectOutputStream ooStream = null;
try {
File file = new File(path);
if (!file.exists()) {
file.createNewFile();
}
foStream = new FileOutputStream(file);
ooStream = new ObjectOutputStream(foStream);
ooStream.writeObject(myClass);
} catch (Throwable t) {
log.error(t);
} finally {
if (ooStream != null) {
try {
ooStream.flush();
ooStream.close();
} catch (IOException e) {
log.error(e);
}
}
}
}
For getting Object:
public MyClass deSerialize(String path) {
MyClass myClass=null;
FileInputStream fiStream = null;
ObjectInputStream oiStream = null;
String errorMessage = "";
try {
File file = new File(path);
if (!file.exists()) {
return null;
}
fiStream = new FileInputStream(path);
oiStream = new ObjectInputStream(fiStream);
Object o = oiStream.readObject();
myClass = (MyClass) o;
} catch (Throwable t) {
log.warn(t);
} finally {
if (oiStream != null) {
try {
oiStream.close();
} catch (IOException e) {
log.error(e);
}
}
}
return myClass;
}
Stacktrace:
java.io.EOFException at
java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2498)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1273)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
at java.util.LinkedList.readObject(LinkedList.java:776) at
sun.reflect.GeneratedMethodAccessor583.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585) at
java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:946)
at
java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1809)
at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1719)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
at
java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1908)
at
java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1832)
at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1719)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
Question:
My serialized object is now corrupted and then is it rubbish now?
Because this object is responsible for rendering the UI which saved by user. If User logs in it should render previously saved state of UI. However for some user the file cannot be deserialized.
EOFException means you are trying to read past the end of the file. Normally you don't have any way of knowing whethere there are more objects to read, other than trying it, so you shouldn't regard EOFException as a problem in the first place. If it is thrown in a situation where you think you know there are more objects in the file, e.g. when you have prefixed an object count to the file, it indicates a problem with the code that wrote the file, or possible corruption of the file itself. Another example is a zero length file that shouldn't be zero length. Whatever the problem is, it can't be solved by the reading end, it is already too late.
I cannot see any problem with the writing and reading of the file.
So my best guess is that the problem is at the file level. For example:
you could be writing one file and reading a different one, or
you could be reading the file before the file write completes, or
something else could be clobbering the file in between the running of your write code and read code.
I suggest that you add some tracing code that uses File.length() to find out what the file size is after you've written it and before you read it.
A couple of other possibilities:
the writer and reader code is using different versions of MyClass (or a dependent class) with incompatible representations and the same serialVersionId values, or
you could be using custom readObject and writeObject methods that are incompatible.
In my case, EOF Exception was solved by ensuring the read and writes to the file were thread safe. Like Stephen C answered above, if you try to write to a file which you also are trying to read from say from another thread, you may be stepping on the ObjectInputStream which is going to throw EOF Exception in this case.