Deserializing Data in Java
I'm trying to read in player data from an array list, but after 2 hours of searching and experimenting, I'm lost.
Here's the deserializing code. It's commented, but basically there should be a file with a Serialized ArrayList of Player objects. I want开发者_Go百科 to deserialize that data and store it in savedPlayers, and then use savedPlayers for a few things.
What did I do wrong?
import java.io.*;
import java.util.*;
public class RoofRunnerApp {
private Scanner in; // Scanner to take playerName input.
private RoofRunnerGame gameTime;
private String filename = "gameData.txt";
public static void main (String[] args) {
System.out.println("WELCOME TO *ROOF RUNNER* \n"); // Welcomes user with game title.
RoofRunnerApp myGame = new RoofRunnerApp();
}
public RoofRunnerApp() {
// 1) Read in name from user.
in = new Scanner(System.in);
System.out.print("Please enter your name: ");
String playerName = in.next();
// 2) Create Player arrayList.
ArrayList<Player> savedPlayers = new ArrayList<Player>();
// 3) Read in Serialized Data from file.
try {
ObjectInputStream input = new ObjectInputStream(new FileInputStream(filename)); // Add file name.
savedPlayers = (ArrayList<Player>)input.readObject();
input.close();
} catch( Exception e ) {
e.printStackTrace();
return;
}
Player thisPlayer; //thisPlayer is passed to Game class.
// 4) if arraylist != empty -> Check for playerName and inputName match.
////// If there's a match -> Set thisPlayer equal to the savedPlayer, using the Player constructor.
if(savedPlayers.length() != 0)
for(int i = 0; i < savedPlayers.length(); i++)
if(playerName.equals(savedPlayers.getName())){
thisPlayer = new Player(savedPlayers[i]);
break;
}
}
else
thisPlayer = new Player(playerName); // If no match -> Set thisPlayer to new player with playerName.
RoofRunnerGame gameTime = new RoofRunnerGame(thisPlayer);
}
I know I'm not supposed to answer, but it's not letting me edit.
UPDATE/QUESTIONS
I haven't serialized any data, yet. Right now I'm just trying to set up the deserialization (and I was going to add in serialization after). But, in Eclipse, when I try the above I get several error messages saying that savedPlayers is not an arrayList and that length() doesn't work on it.
Here's the class code. (The code near the bottom is still in the works. My errors happen in lines 33-37:
import java.io.*;
import java.util.*;
public class RoofRunnerApp {
private Scanner in; // Scanner to take playerName input.
private RoofRunnerGame gameTime;
private String filename = "gameData.txt"; // File to hold Serialized Player data.
public static void main (String[] args) {
System.out.println("WELCOME TO *ROOF RUNNER* \n"); // Welcomes user with game title.
RoofRunnerApp myGame = new RoofRunnerApp();
}
public RoofRunnerApp() {
// 1) Read in name from user.
in = new Scanner(System.in);
System.out.print("Please enter your name: ");
String playerName = in.next();
// 2) Create Player arrayList.
ArrayList<Player> savedPlayers = new ArrayList<Player>();
// 3) Read in Serialized Data from file.
try {
ObjectInputStream input = new ObjectInputStream(new FileInputStream(filename)); // Add file name.
savedPlayers = (ArrayList<Player>)input.readObject();
input.close();
} catch( Exception e ) {
e.printStackTrace();
return;
}
Player thisPlayer; //thisPlayer is passed to Game class.
// 4) if arraylist != empty -> Check for playerName and inputName match.
////// If there's a match -> Set thisPlayer equal to the savedPlayer, using the Player constructor.
if(savedPlayers.length() != 0)
for(int i = 0; i < savedPlayers.length(); i++)
if(playerName.equals(savedPlayers[i].getName())){
thisPlayer = new Player(savedPlayers[i]);
break;
}
}
else
thisPlayer = new Player(playerName); // If no match -> Set thisPlayer to new player with playerName.
RoofRunnerGame gameTime = new RoofRunnerGame(thisPlayer);
// After:
// Exit code in RRG
// 1) Add current Player to current ArrayList.
/*
// Create/Return player objects.
Player p = new Player(playerObject)
savedPlayers.add(p);
///// Save data to file.
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream( new FileOutputStream( "myfile") ); // Add filename.
out.writeObject( savedPlayer ); //write the entire ArrayList
out.close();
} catch( IOException e ) {
e.printStackTrace();
return;
}
*/
}
}
You have to serialize out the object first before you can read it. The format used by ObjectInputStream/ObjectOutputStream is not something you can type out. As such you should with the saving of the objects first into a file, then read them in. So write a class that does the writing and reading of the List first in a class of its own and test that out to get a feel for object serialisation and some of the problems. Test things like no file present, empty file, file with corrupt data, files with a valid list with zero entries etc.
As to your current implementation where you are catching the IOException for the reading you should not printStackTrace and return, its a normal valid case as the file does not currently contain a valid list. So instead you should do nothing in the catch so that the program continues on.
You may also find that the ObjectInputStream is returning null for the savedPlayers variable and you'll want to check that case before you assign the value to the savePlayers variable in that same reading code.
I fixed the code formatting. I assume you're a bit new to java. The error you get about savedPlayers is not that it is not an ArrayList
but that it is not an array. You can't index it like savedPlayers[i]
but must use savedPlayers.get(i)
, where i
is the index. Your main problem seems to be the difference between an ArrayList
and an array. An array is a primitive construct, while an ArrayList
is a type built on top of an array. An actual array would have a length
property (note: not a method!), while ArrayList
has a size()
method. Look up arrays in the java tutorial.
It's considered best practice to refer to types using the most general interface that still supports what you do, in this case that would be List
. If you're new to java it really helps to have the API documentation handy. Look up List
and ArrayList
in there. You might even use Collection
if you don't really care that order is preserved here, i.e. when you output a list to disk initialise it as:
Collection<Player> players = new ArrayList<Player>();
Collection
doesn't have positional access though, so stick to List
if you need that.
Another tip, you're using a for-loop to iterate over all the players, but collections such as List
have iterators for this. It's generally more efficient when not using an ArrayList
. There is a for-loop construct that you can use to iterate over all objects in a collection:
for (Player player : players) {
// do something with each Player
}
Sorry for not editing again. I'm changing computers constantly. Anyways...
Why do you say you have to serialize the objects first? I'm trying to do this:
- Have user enter his playername.
- Check the gameData file to see if any data with that player's name has been saved.
If player name matches one in file -> create a Player object (thisPlayer) with that data.
If player name has no matches || file is empty -> create a Player object (this Player) with just that name and new data.
- Then it would run the game.
- THEENNN it would serialize the data and save it to the file.
It seems to me you have to deserialize the input at the beginning when loading data, and then serialize at the end when saving data, yeah?
Here's the code now. There's one error in the whole file. It says that thisPlayer may not have been initialized in line 46. Any ideas?
import java.io.*;
import java.util.*;
public class RoofRunnerApp {
private Scanner in; // Scanner to take playerName input.
private RoofRunnerGame gameTime;
private String filename = "gameData.txt"; // File to hold Serialized Player data.
public static void main (String[] args) {
System.out.println("WELCOME TO *ROOF RUNNER* \n"); // Welcomes user with game title.
RoofRunnerApp myGame = new RoofRunnerApp();
}
public RoofRunnerApp() {
// 1) Read in name from user.
in = new Scanner(System.in);
System.out.print("Please enter your name: ");
String playerName = in.next();
// 2) Create Player arrayList.
ArrayList<Player> savedPlayers = new ArrayList<Player>();
// 3) Read in Serialized Data from file.
try {
ObjectInputStream input = new ObjectInputStream(new FileInputStream(filename)); // Add file name.
savedPlayers = (ArrayList<Player>)input.readObject();
input.close();
} catch( Exception e ) {
e.printStackTrace();
return;
}
boolean notFound = true;
Player thisPlayer; //thisPlayer is passed to Game class.
// 4) if arraylist != empty -> Check for playerName and inputName match.
////// If there's a match -> Set thisPlayer equal to the savedPlayer, using the Player constructor.
if(savedPlayers.size() != 0){
for(int i = 0; i < savedPlayers.size(); i++){
if(playerName.equals(savedPlayers.get(i).getName())){
thisPlayer = new Player(savedPlayers.get(i));
notFound = false;
break;
}
}
}
if(savedPlayers.size() == 0 || notFound)
thisPlayer = new Player(playerName); // If no match -> Set thisPlayer to new player with playerName.
RoofRunnerGame gameTime = new RoofRunnerGame(thisPlayer);
}
精彩评论