Object serialization and try/catch

  • (2 Pages)
  • +
  • 1
  • 2

15 Replies - 970 Views - Last Post: 30 January 2013 - 05:13 PM Rate Topic: -----

#1 IceHot  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 220
  • Joined: 28-August 12

Object serialization and try/catch

Posted 19 January 2013 - 12:52 AM

I am having some trouble understanding the order of execution in the try/catch statement. Staying close to the code in my textbook (for purposes of understanding their code), I have the following in my WriteData.java file:
import java.io.*;
import java.util.Scanner;

public class WriteData 
{
	private static int number;
	private static String name; 
	private static float money;
	private static ObjectOutputStream output;	//This is for the output. Make sure that
	//this object gets an instance of FileOutputStream so that it can write objects
	//to a FILE.
	static Scanner input = new Scanner(System.in);
	static DataClass d;
	
	public static void openfile()
	{
		//Try opening a file (it must have the ".ser" extension).
		try
		{
			output = new ObjectOutputStream(new FileOutputStream("test.ser"));
		}
		//If there is a failure, throw the necessary error.
		catch (IOException exception)
		{
			System.out.println("Error opening file.");
		}
	}
	public static void writedata()
	{
		//write the data until the user enters a sentry value.
		System.out.println("Enter CTRL + z to stop input.\n");
		while (input.hasNext())
		{
			System.out.print ("Enter the data in the following format: " +
						"account_number name balance\n->");
			try
			{
				number = input.nextInt();
				name = input.next();
				money = input.nextFloat();
				
				//Make object with that data
				d = new DataClass(number, name, money);
				//write it to the file
				output.writeObject(d);
			}
			catch (IOException e)
			{
				System.out.println("Error writing to file.");
				return;
			}
		}
		System.out.println("\n");
	}	//end writedata
	public static void closefile()
	{
		try 
		{
			if (output != null)
			{
				output.close();
			}
		}
		catch (IOException e)
		{
			System.out.println("Error closing file. Take precautions");
			System.exit(1);
		}
	}
}


When this executes, it wants to, for some reason, wait for my input and then prompt me for it! There has to be something wrong here! For some reason, the textbook put the prompt at the end of the while statement (and after all the try-catch statements), and I don't understand the flow of such statements. Also, in the ReadData.java file, I went closer to what they were trying to do. I don't feel comfortable with using the following infinite loop:
while (true)
{
//read in objects
}
catch (EOFException eof)
{
	return;
} 


I think this is because I have done most of my programming in C++, where there exist features like:
while (myfile.good())
{
        //some stuff
}


Is this natural? (My game MIGHT have to read in all the data from the .ser file; it will be storing encrypted data to the file for the purpose of conducting a beta-test.)

This post has been edited by IceHot: 19 January 2013 - 12:30 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Object serialization and try/catch

#2 Flukeshot  Icon User is offline

  • A little too OCD
  • member icon

Reputation: 417
  • View blog
  • Posts: 1,030
  • Joined: 14-November 12

Re: Object serialization and try/catch

Posted 19 January 2013 - 04:54 AM

Output is writing not reading. You want a FileReader and BufferedReader to read a file. Here's an example from my own coursework:
   private void read() {

      int retVal = fHandler.showOpenDialog(fHandler);
      if(retVal == JFileChooser.APPROVE_OPTION) {
         //Get target file's name
         fileName = fHandler.getSelectedFile().getAbsolutePath();
         
         //Create a new File object with the received data
         File input = new File(fileName);
         
         //Read file contents to the text area
            //(I/O operations must be performed in
            //a try/catch(IOException) block.
         
         try {
            
            fr = new FileReader(input);
            br = new BufferedReader(fr);
            String s;
            
            while((s = br.readLine()) != null) {
               PAGE_page.append(s + "\n");
            }
            
            br.close();
            
         } catch (IOException e1) {
            System.out.println(e1);
         }
      }
   }
   
   private void write() {
      
      int retVal = fHandler.showSaveDialog(fHandler);
      if(retVal == JFileChooser.APPROVE_OPTION) {
         //Get target
         fileName = fHandler.getSelectedFile().getAbsolutePath();
         
         //Create a new File object with the received data
         File output = new File(fileName);
         
         //Write file contents to the text file
            //(I/O operations must be performed in
            //a try/catch(IOException) block.
         try {
            
            fw = new FileWriter(output);
            pw = new PrintWriter(fw);
            
            pw.println(PAGE_page.getText());
            pw.flush();
            
            pw.close();
            
         } catch (IOException e1) {
            System.out.println(e1);
         }
      }
   }



Remember that the flow is always:-

INPUT => PROGRAM => OUTPUT
Was This Post Helpful? 0
  • +
  • -

#3 g00se  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2831
  • View blog
  • Posts: 11,986
  • Joined: 20-September 08

Re: Object serialization and try/catch

Posted 19 January 2013 - 05:01 AM

It's not possible to say anything with any certainty about of execution, as you don't show any execution - there's no main method visible.

Quote

I don't feel comfortable with using the following infinite loop:
It's not brilliant and should normally be avoided, but it's not possible to avoid with Object streams unless you know exactly how many objects there are to read/write.

I don't really unnderstand your last point about C++ as it seems a non sequitur. Java too has such features, and your example could be Java code.
Was This Post Helpful? 0
  • +
  • -

#4 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8346
  • View blog
  • Posts: 31,904
  • Joined: 06-March 08

Re: Object serialization and try/catch

Posted 19 January 2013 - 10:45 AM

You have comments completly false, I hope you don't expect the code to do what they claim the code do

         //If there is a failure, throw the necessary error.  
         catch (IOException exception)  
         {  
             System.out.println("Error opening file.");  
         }  


NO... if there is a failure you simply print it on the console and continue
the like if nothing happenned. No Exception throwed to inform the caller of this
method that the file couldn't be opened
Now how will the caller behave thinking that the file was opened is another story

In file processing, just doing a println() in a catch() clause is kind of not very useful
Was This Post Helpful? 0
  • +
  • -

#5 IceHot  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 220
  • Joined: 28-August 12

Re: Object serialization and try/catch

Posted 19 January 2013 - 01:04 PM

Sorry...I mixed up the names. It is now fixed both on here and on my computer. I think this answers most of my questions. pbl, good point: I should get right on that. Also, I have no idea why a renowned textbook is using an infinite while-loop, but I now know a way to avoid using one. This is a good thing because my game needs this file to analyze the player's performance in the beta-test. Also, my unanswered question is a rather trivial one because the game will be doing the input, not the user.
Was This Post Helpful? 0
  • +
  • -

#6 g00se  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2831
  • View blog
  • Posts: 11,986
  • Joined: 20-September 08

Re: Object serialization and try/catch

Posted 19 January 2013 - 03:41 PM

Quote

Also, I have no idea why a renowned textbook is using an infinite while-loop
But i just told you why essentially ..?
Was This Post Helpful? 0
  • +
  • -

#7 IceHot  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 220
  • Joined: 28-August 12

Re: Object serialization and try/catch

Posted 20 January 2013 - 12:17 AM

Sorry...had to think it over...I typed it before fully considering your answer, g00se. (I should have just let it sit.) Anyways, considering that answer, I still plan on making the modifications to the game such that it will capture the results that Joe User ends up with at the end of each game. Avoiding the while-loop, I see I have three options (which will have the same effect):
1.) save the number of times the player has played the game to the first object written in the .ser file and increment this number every time a game has been completed by setting the write "pointer" to that object
2.) same as number 1 except bring in EVERY LAST INSTANCE INTO AN ARRAY, modify the first one, and write the whole array to the file (assuming the user plays n times, that will result in a complexity of O(Math.pow(n,2)))
3.) write two .ser files; the first one having just this number of times played and the second one having the rest of the data. Implementations for this idea would be to either have two different objects or just overload the constructor so that this number can be part of a constructor.

The third object seems the most seductive one as it sounds easier than the other two. I am wondering if it will be the BEST option. What do you all think?

This post has been edited by IceHot: 20 January 2013 - 12:19 AM

Was This Post Helpful? 0
  • +
  • -

#8 g00se  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2831
  • View blog
  • Posts: 11,986
  • Joined: 20-September 08

Re: Object serialization and try/catch

Posted 20 January 2013 - 04:29 AM

The simplest way is to serialize a List<Game>. That way, there's only one invocation of read/writeObject necessary
Was This Post Helpful? 0
  • +
  • -

#9 IceHot  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 220
  • Joined: 28-August 12

Re: Object serialization and try/catch

Posted 20 January 2013 - 02:41 PM

which would work fine if the user kept playing. But the idea is extendable to when they play just once.
Was This Post Helpful? 0
  • +
  • -

#10 g00se  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2831
  • View blog
  • Posts: 11,986
  • Joined: 20-September 08

Re: Object serialization and try/catch

Posted 20 January 2013 - 02:46 PM

Sorry - i don't get your point - the List is serializable with size 0-n ..?
Was This Post Helpful? 0
  • +
  • -

#11 IceHot  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 220
  • Joined: 28-August 12

Re: Object serialization and try/catch

Posted 20 January 2013 - 09:08 PM

What I am saying is that I will just write the objects to the List (if it is serializable; from what you are telling me, it is), and write the list to the end of the file each time the game is ended.
Was This Post Helpful? 0
  • +
  • -

#12 IceHot  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 220
  • Joined: 28-August 12

Re: Object serialization and try/catch

Posted 23 January 2013 - 09:16 PM

There is one problem with this: I am generating the data in Game, when the objects are of type GameData, and when I try to declare a private list, it tells me I need to explicitly
import java.util.List
when I already done
import java.util.*;
!! Oh, and there is no need for the file that keeps track of the objects in the .ser file to also be of type .ser; it will only contain one number!! (Note to self...)
Was This Post Helpful? 0
  • +
  • -

#13 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8346
  • View blog
  • Posts: 31,904
  • Joined: 06-March 08

Re: Object serialization and try/catch

Posted 24 January 2013 - 04:50 AM

A private List you mean ?
Must be because you have 2 classes named List

And List from util is an Interface
Was This Post Helpful? 0
  • +
  • -

#14 IceHot  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 220
  • Joined: 28-August 12

Re: Object serialization and try/catch

Posted 24 January 2013 - 12:07 PM

Yes, a private List. and no, I don't have two classes named List. I was trying something like
private List <GameData> records;

Was This Post Helpful? 0
  • +
  • -

#15 IceHot  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 220
  • Joined: 28-August 12

Re: Object serialization and try/catch

Posted 29 January 2013 - 09:26 PM

That error is solved, I think. Now, I am having trouble the game being played multiple times. It works when I simulate just one time the game is run, but any more than that, and it throws the following type of error:

java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at LoadData.loadrecords(LoadData.java:167)

It is complaining on this line:
recorddata = (ArrayList<GameData>)objectreader.readObject();
After some searching, http://stackoverflow...id-type-code-ac, I found some explanation, but what gets me is the fact that I feel FORCED to code the way that is triggering that error. The data that is displaying isn't all the way correct, either. Does anyone on here know another way to write and fetch data written to files when the user decides to end the program? This is what I ended up doing:

SaveData.java
import java.io.*;
import java.util.*;
import javax.swing.JOptionPane.*;

public class SaveData
{
	private int timesopened;
	private FileInputStream fi;
	private FileOutputStream binaryfile;
	private FileOutputStream recordfile;
	private ObjectOutputStream objectrecorder;
	private boolean isthere;
	public SaveData()
	{
		//In this constructor, you should probably try opening the file with the
		//number of instances in it.
		//If you succeed, take in that number and set isthere to true.
		//If you fail, create the file.
		isthere = true;
		try
		{
			fi = new FileInputStream("counter.bin");
			timesopened = fi.read();
		}
		catch (IOException e)
		{
			isthere = false;
			try
			{
				binaryfile = new FileOutputStream("counter.bin");
				binaryfile.write(1);
			}
			catch (FileNotFoundException e1)
			{
				//Just a reminder to replace EVERY LAST INSTANCE of the below code
				//with something that will alert the player to contact you with a
				//screenshot of the error.
				e1.printStackTrace();
				System.exit(1);
			}
			catch (IOException ex)
			{
				ex.printStackTrace();
				System.exit(1);
			}
		}
	}	//end null constructor

	public void writedata (ArrayList <GameData> somelist)
	{
		if (isthere)
		{
			timesopened++;
			//open the binary file again
			try
			{
				binaryfile = new FileOutputStream("counter.bin");
				binaryfile.write(timesopened);
			}
			catch (FileNotFoundException e)
			{
				//Replace this with GUI code.
				e.printStackTrace();
				System.exit(1);
			}
			catch (IOException e)
			{
				//Replace this with GUI code.
				e.printStackTrace();
				System.exit(1);
			}
			//open the game records file with the append option
			try
			{
				recordfile = new FileOutputStream("record.ser", true);
			}
			catch (FileNotFoundException fnf)
			{
				//Replace this with GUI code.
				fnf.printStackTrace();
				System.exit(1);
			}
		}	//end if
		else
		{
			System.out.println("You saw me!");
			try
			{
				recordfile = new FileOutputStream("record.ser");
			}
			catch (FileNotFoundException e)
			{
				//Replace this with GUI code.
				e.printStackTrace();
				System.exit(1);
			}
		}	//end else
		try
		{
			objectrecorder = new ObjectOutputStream(recordfile);
			objectrecorder.writeObject(somelist);
		}
		catch (IOException ex)
		{
			//Replace this with GUI code.
			ex.printStackTrace();
			System.exit(1);
		}
	}	//end writedata
	public void closefile()
	{
		try
		{
			if (objectrecorder != null)
			{
				objectrecorder.close();
			}
		}
		catch (IOException e)
		{
			//Replace this with GUI code.
			e.printStackTrace();
			System.exit(1);
		}
	}	//end closefile

}	//end class



LoadData.java
import java.util.List;
import java.util.ArrayList;
import java.io.*;

public class LoadData
{
	private FileInputStream recordfrequency;
	private ObjectInputStream objectreader;
	private ArrayList recorddata;
	private int[] timesplayed, numright, numwrong;
	private long[] avgtime, fastesttime, slowesttime;
	private float[] accuracy;
	private int recordnum;
	//You should have "high-score" and "low-score" variables here...
	//The data should all be arrays so that there is exactly one variable for every
	//game difficulty...
	public LoadData()
	{
		//initialize everything
		recorddata = new ArrayList<GameData>();
		timesplayed = new int[5];
		numright = new int[5];
		numwrong = new int[5];
		avgtime = new long[5];
		fastesttime = new long[5];
		slowesttime = new long[5];
		accuracy = new float[5];
		//Setting the default fastesttime equal to the number of milliseconds in one
		//day
		for (int n = 0; n < 5; n++)
		{
			fastesttime[n] = 86400000;
		}
		try
		{
			objectreader = new ObjectInputStream((new FileInputStream("record.ser")));
			recordfrequency = new FileInputStream("counter.bin");
			recordnum = recordfrequency.read();
		}
		catch (FileNotFoundException fnf)
		{
			//Replace this with GUI code.
			fnf.printStackTrace();
			System.exit(1);
		}
		catch (IOException e)
		{
			//Replace this with GUI code.
			e.printStackTrace();
			System.exit(1);
		}
	}	//end default constructor

	//Here it would make sense to set those methods that set those "high-scores" and
	//"low-scores". They should take in lists so that they can be called for every
	//record in the file. They should also be void so that they can be called over
	//and over again without returning multiple values. They should be simply private
	//methods that set private variables...
	private void settimesplayed(ArrayList<GameData> record)
	{
		//for every object on the list
		for (int index = 0; index < record.size(); index++)
		{
			//get the number of times played and just increment the variable for the
			//associated difficulty by that amount
			timesplayed[(record.get(index)).getlevel() - 1]++;
		}
	}	//end settimesplayed
	private void setfastesttime(ArrayList<GameData> record)
	{
		//for every object on the list
		for (int index = 0; index < record.size(); index++)
		{
			//if the associated completion time is less than the "high-score"
			if (fastesttime[(record.get(index)).getlevel() - 1] >
			(record.get(index)).gettime())
			{
				//set the new "high-score" time
				fastesttime[(record.get(index)).getlevel() - 1] =
						(record.get(index)).gettime();
			}

		}
	}	//end setfastesttime
	private void setslowesttime(ArrayList<GameData> record)
	{
		//for every object on the list
		for (int index = 0; index < record.size(); index++)
		{
			//if the associated completion time is more than the "lowest-score"
			if (slowesttime[(record.get(index)).getlevel() - 1] <
					(record.get(index)).gettime())
			{
				//set the new "lowest-score" time
				slowesttime[(record.get(index)).getlevel() - 1] =
						(record.get(index)).gettime();
			}
		}
	}	//end setslowesttime
	private void setavgtime(ArrayList<GameData> record, boolean islastcall)
	{
		//for every object on the list
		for (int index = 0; index < record.size(); index++)
		{
			//increment the totaltime variable associated with the difficulty level
			//let this variable be simply the respective spot in avgtime
			avgtime[(record.get(index)).getlevel()-1]+=(record.get(index)).gettime();
			if (islastcall)
			{
				//if this is the last item on the list
				if (index == record.size() - 1)
				{
					//set avgtime[difficultylevel] = total_time / numTimesPlayed
					for (int i = 0; i < 5; i++)
					{
						if (timesplayed[i] != 0)
						{
							avgtime[i] = avgtime[i]/timesplayed[i];
						}
						else
						{
							avgtime[i] = 0;
						}
					}
				}
			}
		}
	}	//end setavgtime
	private void setnumright(ArrayList<GameData> record)
	{
		//for every object on the list
		for (int index = 0; index < record.size(); index++)
		{
			//increment numright by the amount right (according to difficulty level)
			numright[(record.get(index)).getlevel() - 1]+= 
					(record.get(index)).getnumright();
		}
	}	//end setnumright
	private void setnumwrong(ArrayList<GameData> record)
	{
		//for every object on the list
		for (int index = 0; index < record.size(); index++)
		{
			//same as setnumwrong, but with the numwrong[difficultylevel]
			numwrong[(record.get(index)).getlevel() - 1]+=
					(record.get(index)).getnumwrong();
		}
	}	//end setnumwrong
	private void setpercent()
	{
		//for each difficultylevel
		for (int index = 0; index < 5; index++)
		{
			if ((numright[index] != 0) && (numwrong[index] != 0))
			{
				accuracy[index] = numright[index] / (numright[index] 
						+ numwrong[index]);
			}
			else 
			{
				accuracy[index] = 0;
			}
		}
	}	//end setpercent
	public void loadrecords()
	{
		 //for every record in the list
		for (int x = 0; x < recordnum; x++)
		{
			System.out.println("x == " + x);
			try
			{
				recorddata = (ArrayList<GameData>)objectreader.readObject();
			}
			catch (ClassNotFoundException e)
			{
				//Replace this with GUI code.
				e.printStackTrace();
			}
			catch (IOException e)
			{
				//Replace this with GUI code.
				e.printStackTrace();
				
			}
			//Here should go calls to those methods that set "records".
			settimesplayed(recorddata);
			setfastesttime(recorddata);
			setslowesttime(recorddata);
			if (x != recordnum - 1)
			{
				setavgtime(recorddata, false);
			}
			else
			{
				setavgtime(recorddata, true);
			}
			setnumright(recorddata);
			setnumwrong(recorddata);
			if (x == recordnum - 1)
			{
				setpercent();
			}
		}
	}	//end loadrecords
	//The purpose of these getters will be to send data to the AbstractTableModel.
	public long getavgtime(int index)
	{
		return this.avgtime[index];
	}
	public long getfastesttime(int index)
	{
		return this.fastesttime[index];
	}
	public long getslowesttime(int index)
	{
		return this.slowesttime[index];
	}
	public int gettimesplayed(int index)
	{
		return this.timesplayed[index];
	}
	public int getnumright(int index)
	{
		return this.numright[index];
	}
	public int getnumwrong(int index)
	{
		return this.numwrong[index];
	}
	public float getpercent(int index)
	{
		return this.accuracy[index];
	}
	public void closefile()
	{
		try
		{
			if (objectreader != null)
			{
				objectreader.close();
			}
		}
		catch (IOException ex)
		{
			//Replace this with GUI code.
			ex.printStackTrace();
			System.exit(1);
		}
	}	//end closefile
}


This post has been edited by IceHot: 29 January 2013 - 09:50 PM

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2