I have a a problem I have been dealing with for quite some time now. When attempting to de-serialize my custom "Sound" objects in a folder I continue to get 3 exceptions. IOException, NullPointerException, and StreamCorruptedException. Please take a look:
Method for reading sounds:
public static Sound readSound(String loc){
try{
FileInputStream fis = new FileInputStream(loc);
ObjectInputStream ois = new ObjectInputStream(fis);
fis.close();
ois.close();
return (Sound)ois.readObject();
}catch(Exception e){
System.out.println("Failed to read a serialized object.");
e.printStackTrace();
return null;
}
}
Exceptions/Errors Received: http://gyazo.com/b53faa9590adf6448bf14db11f275325
(Too much to paste here and it pastes incorrectly)
Loading the sounds:
(add sound just adds the sound to an ArrayList as well as a JComboBox)
private static File saveDirFile = new File("/Users/francisj12/Desktop/ACData/");
private static File saveDirFileSounds = new File(saveDirFile.getPath()+"/sounds/");
public static void loadAllSounds(){
if(!saveDirFile.exists()){
saveDirFile.mkdir();
}
if(!saveDirFileSounds.exists()){
saveDirFileSounds.mkdir();
}
for(int x=0; x<saveDirFileSounds.list().length; x++){
try{
File sndFl = new File(saveDirFileSounds.listFiles()[x].getPath());
Sound newSound = Serialize.readSound(sndFl.getPath());
addSound(newSound);
}catch(Exception e){
e.printStackTrace();
continue;
}
}
}
Here it what the .ser files look like: (Once I started using transient on variables so I could serialize my custom Sound object which I dont understand transient yet, it started making the .ser look as follows instead of a ton of weird characters its just one line of weird characters now)
¨ÌsrAlarms.SoundË.®ŸÓÓxp
Hope this is all the information you guys will need thanks so much for your help!
Related
I'm new serialization (and programming in general) so i don't really know what happens under the hood. I'm making an email client program and the class
FileHandlerObject is used to write and read email messages that i send. I maintain an ArrayList and it is read, updated with new email and then written again. I don't understand why it throws an InvalidClassException because the file contains an ArrayList so the casting should be no problem.
I'm maintaining an ArrayList because the writeObject() truncates the file every time it writes.(Let me know if im wrong here)
class FileHandlerObject implements MyFileHandler<EmailMessage>{
public void write(EmailMessage input){
try
{
FileInputStream fileInputStream=new FileInputStream("emails.ser");
ObjectInputStream objectInputStream=new ObjectInputStream(fileInputStream);
#SuppressWarnings("unchecked")
ArrayList<EmailMessage> messagelist= (ArrayList<EmailMessage>) objectInputStream.readObject();
objectInputStream.close();
messagelist.add(input);
FileOutputStream fileOutputStream = new FileOutputStream("emails.ser");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(messagelist);
objectOutputStream.flush();
objectOutputStream.close();
}
catch(FileNotFoundException f)
{
try{
FileOutputStream fileOutputStream = new FileOutputStream("emails.ser");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
ArrayList<EmailMessage> messagelist=new ArrayList<EmailMessage>();
messagelist.add(input);
objectOutputStream.writeObject(messagelist);
objectOutputStream.flush();
objectOutputStream.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
catch(IOException e){
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
public ArrayList<EmailMessage> read(){
try{
FileInputStream fileInputStream=new FileInputStream("emails.ser");
ObjectInputStream objectInputStream=new ObjectInputStream(fileInputStream);
#SuppressWarnings("unchecked")
ArrayList<EmailMessage> messagelist= (ArrayList<EmailMessage>) objectInputStream.readObject();
objectInputStream.close();
return messagelist;
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException c)
{
c.printStackTrace();
}
catch(ClassCastException c)
{
c.printStackTrace();
}
return null;
}
As the docs explain, this means one of a few things. The code you pasted does not give any insights about which of these mistakes you've made.
You saved some emails. Then, you edited the EmailMessage class, for example by adding a method or changing the name of a field, and then you ran the code again which ends up reading that file that was 'saved' with an old version of EmailMessage and which you are now trying to read with a new version. The java serialization mechanism can theoretically deal with versioning schemes but in practice it's a disaster. Ditch serialization, write your own protocol instead.
The EmailMessage class does not implement Serializable and does not have a no-args constructor. Give it a no-args constructor, and add implements Serializable to it.
Your classpath is incomplete; EmailMessage contains fields or methods that refer to some other class you wrote and it is not available on the classpath right now. Fix your classpath.
public class Inventory implements Serializable {
ArrayList<Product> productlist;
File file;
public Inventory(){
productlist = new ArrayList<Product>();
file = new File("build/classes/inventory/inv.ser");
if(!file.exists()){
try {
file.getParentFile().mkdirs();
file.createNewFile();
} catch (IOException ex) {
Logger.getLogger(Inventory.class.getName()).log(Level.SEVERE, null, ex);
}
}
if(file.length() !=0){
loadFile(file);
}
}
public void addProduct(Product product){
productlist.add(product);
saveFile(this.file);
}
public void saveFile(File file){
try{
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream out = new ObjectOutputStream(fos);
out.writeObject(productlist);
out.close();
fos.close();
} catch(FileNotFoundException ex){System.out.println("FileNotFoundException");}
catch(IOException ex){System.out.println("InputException");}
}
public void loadFile(File file){
try{
FileInputStream fis = new FileInputStream(file);
ObjectInputStream in = new ObjectInputStream(fis);
productlist=(ArrayList<Product>)in.readObject();
in.close();
fis.close();
} catch(FileNotFoundException ex){ System.out.println("FileNotFoundException"); }
catch(IOException ex){System.out.println("OutputException");}
catch(ClassNotFoundException ex){System.out.println("ClassNotFoundException");}
}
}
Does writeObject() overwrite the content of the existing file or append the objects to the existing file?
And is it a good idea to serialize an ArrayList of Objects like what i did inside the saveFile method?
Does writeObject() overwrite the content of the existing file or append the objects to the existing file?
Neither. It writes the object to the underlying stream. The underlying stream is a serial byte stream that can only be appended to. In this case the underlying stream is backed by an underlying file, which has or has not already been overwritten, depending on how you constructed the FileOutputStream. It has nothing to do with writeObject(). In any case you can't successfully append to a file of serialized objects without taking special measures.
And is it a good idea to serialize an ArrayList of Objects like what i did inside the saveFile method?
Compared to what?
N.B.
When you get an exception, print it. Not just some message of your own devising.
Creating a file just so you can test it for zero length doesn't make sense.
The directory build/classes/inventory won't be there at runtime once you stop using the IDE. This is no place to put a file.
You could try FileUtils function to write list of object into plane text file.
Please find below URL for reference -
http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/FileUtils.html#writeLines-java.io.File-java.util.Collection-java.lang.String-boolean-
e.g.
FileUtils.writeLines(new File(fileToAttach), list);
I've been trying to do this on my own for the past couple hours and am kinda losing it a little.
All I want to do is open a file, read it and display it to the console; that's it.
I'm using eclipse to develop for android 2.3.3.
I have tried using a bunch of different ways with code that I have found here, and on other sites. Here is what I have now and how its all called:
In the OnCreate function:
setContentView(new TestMap(this));
The testMap class:
TestMap(Context context){
super(context);
// might need to be on the panel class
loadTileFile("worldonelayout.txt", context);
in the same class:
private void loadTileFile (String filename, Context context){
FileInputStream input = null;
InputStreamReader reader = null;
char[] inputBuffer = new char[256];
String data = null;
try {
input = context.openFileInput("worldonelayout.txt");
reader = new InputStreamReader(input);
reader.read(inputBuffer);
data = new String(inputBuffer);
System.out.println(data);
Toast.makeText(context, "Text read", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(context, "Text not read", Toast.LENGTH_SHORT).show();
} finally {
try {
input.close();
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
This code doesnt work. It always hits the exception.
"/data/data/com.name.somethingiremoved/files/worldonelayout.txt (No such file or directory)".
This happens at the first CATCH. BTW my file is in the root directory: Documents\Eclipse\workspace\project\worldonelayout.txt. I can also see the file in the browser on the left
From what I have seen here and on other sites, it is something to do with the Context class being derived from the Activity? I don't want to have this code in the same class as my activity. Is there a way round this?
If you need anything more from me, let me know.
The open file is looking for a file on the phone's file system, not on the computer's. Its telling you exactly where it expects to find it - on the phone under /data/data/com.name.somethingiremoved/files/worldonelayout.txt
I have a client application program that has 10+ classes each with 100+ components that need to be kept track of. When the program is run the user inputs numbers, selects items, toogles checkboxes, etc. I need to come up with a way to save all of the data input when the program is closed and have the capability of when the program is run again grab all the data from a previous time being run.
I have looked into Serialization but some of the things I need saved are not serializable so that didn't work. I have also looked into SingleFrameApplication and session storage but only in vain.
Writing to a file would cause the need for hours of tedious coding and would probably be inefficient. Does anyone have any ideas of how else I could tackle this hairy beast of a problem?
Update:
Doing what #home suggest I did the following:
public Main() throws FileNotFoundException {
initComponents();
//read the file
Read();
//...
}
private void formWindowClosing(java.awt.event.WindowEvent evt) {
try {
//write to the file, the program is closing
Write();
} catch (FileNotFoundException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void Read() throws FileNotFoundException {
try{
XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(new FileInputStream("test.xml")));
//set the JTabbedPane to what is in the file
tab = (JTabbedPane) decoder.readObject();
decoder.close();
}catch(Exception e){
//there was no test.xml file so create one
XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("test.xml")));
encoder.writeObject(null);
encoder.close();
}
}
private void Write() throws FileNotFoundException {
XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("test.xml")));
//clear all previous things in the file
encoder.flush();
//write the JTabbedPane into the file
encoder.writeObject(tab);
encoder.close();
}
After these changes all that pops up when I run the program is a blank JTabbedPane. Can anyone explain why this is the case?
If you simply want to serialize an object compatible with JavaBeans specification, look at XML Encoder and Decoder: http://download.oracle.com/javase/6/docs/api/java/beans/XMLEncoder.html, http://download.oracle.com/javase/6/docs/api/java/beans/XMLDecoder.html
EDIT: Tutorial here: http://java.sun.com/products/jfc/tsc/articles/persistence4/
I'm trying to write an Android game and I would like to be able to pause the game even if the user wants to return to the main menu or the activity gets killed off by the system. onSaveInstanceState doesn't seem to give me a whole lot of control as to when I can read the bundle back, plus from what I can tell, the bundle is only good for short periods of time. So I want to serialize a few ArrayLists that I have, then read them back. I don't get any compile errors nor does the program crash. But, the data either never gets written or never gets read. I'm not sure which one. My serializeData method is called in onDestroy and the deserializeData is called from onCreate. Here's my code for writing and reading the data:
public void serializeData(String filename, ArrayList<String>arrayList) {
FileOutputStream fos;
try {
fos = openFileOutput(filename, Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(arrayList);
oos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
#SuppressWarnings("unchecked")
private void deserializeData(String filename, ArrayList<String>arrayList){
try{
FileInputStream fis = openFileInput(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
arrayList = (ArrayList<String>)ois.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}
Any help would be greatly appreciated! Thanks in advance!
Let me tell you one thing: never use the onDestroy() method to save your data. Use onPause() or onStop() instead. You should never count on the onDestroy() method to save data or call some functions.
Use onDestroy to close connections and finish using resources and the like. If you want to read more about this you should take a look here.
Other than that your code seems fine. Just add one more thing: put a oos.flush() just above oos.close().
And don't forget to close the objectInputStream object.
I cannot see an obvious problem with that code.
I'd try adding some code after closing the ObjectOutputStream and before opening the ObjectInputStream to print out the absolute name and size of the file.
While serializing you can write to ByteArrayOutputStream and then decode the bytes into string using platform's default character set. Store this string into SharedPreferences. While deserializing, just get the bytes from string and create a ByteArrayInputStream using this and feed it to ObjectInputStream.Are you sure your activity is being killed? It might be the case that your activity is oscillating between onPasue/onResume.