I'm working on a school project which consist in creating race-tournaments
I'm having an issue right now because I have multiple races-type (CarRace/BikeRace) which have Race as a parent
I'm saving an array of races no matter the specific type.
And now I need to load this list of races
public static ArrayList<Course> loadLRace(String name) {
File inFile = new File(name+".txt");
FileInputStream inFileStream;
ArrayList<Race> lRace = new ArrayList<Race>();
try {
inFileStream = new FileInputStream(inFile);
ObjectInputStream inObjectStream = new ObjectInputStream(inFileStream);
int length = inObjectStream.readInt();
for(int i = 0; i < length; i++) {
Race race = (Race)inObjectStream.readObject();
lRace.add(Race);
}
inObjectStream.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
return lRace;
}
And I'm having a "non valid constructor" error, I guess this is because I don't deal with CarRace AND BikeRace separately, but how can I ?
Related
public static void main(String[] args) {
try {
Path file = Paths.get("file.jar"); // 100mb file
for (int i = 0; i < 10; i++) {
byte[] toCollect = Files.readAllBytes(file);
toCollect = null;
}
System.gc();
} catch (Exception e) {
e.printStackTrace();
}
new Thread(() - > {
try {
Thread.sleep(100000000L);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
After executing this code the program uses 1GB of RAM, why?
This code reads bytes from a file using the JAVA API and puts them into an array, then assigns null to that array.
my code has to read in two different Object Types (Bestellung, AKunde) through a ObjectOutputStream and save it in a csv file, which works.
But when i try to read them from the file it doesn't work.
Here is the code:
OutputStream:
LinkedList<Bestellung> bestellListe = verwaltungBestell.getBestellListe();
try {
fileOutputStream = new FileOutputStream(file);
outputStream = new ObjectOutputStream(fileOutputStream);
for (AKunde kunde : kundenliste) {
outputStream.writeObject(kunde);
}
for (Bestellung bestellung : bestellListe) {
outputStream.writeObject(bestellung);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
InputStream:
ArrayList<AKunde> kundenImport = new ArrayList<AKunde>();
ArrayList<Bestellung> bestellungenImport = new ArrayList<Bestellung>();
boolean cont = true;
try {
ObjectInputStream objectStream = new ObjectInputStream(new FileInputStream(directorie));
while (cont) {
AKunde kunde = null;
try {
kunde = (AKunde) objectStream.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (kunde != null) {
kundenImport.add(kunde);
} else {
cont = false;
}
}
while (cont) {
Bestellung bestellung = null;
try {
bestellung = (Bestellung) objectStream.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (bestellung != null) {
bestellungenImport.add(bestellung);
} else {
cont = false;
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
}
But it won't read the "Bestellungen" and won't save them into "bestellungenImport".
Anyone has a solution???
Your code never reaches the Bestellung reader part.
You have a false assumption that kunde =(AKunde)objectStream.readObject(); returns null.
Instead, it throws exception.
Oneway you can do is cast it like #luk2302.
Another way is to add a object count when writing your object stream:
outputStream.writeInt(kundenliste.size());
for (AKunde kunde : kundenliste) {
outputStream.writeObject(kunde);
}
outputStream.writeInt(bestellListe.size());
for (Bestellung bestellung : bestellListe) {
outputStream.writeObject(bestellung);
}
Then replace your while(cont) loop with a for each loop:
int kundeCount = objectStream.readInt();
for (int i = 0; i < kundeCount; i++) {
// Read and import kunde
}
You need to change your logic for reading objects. There are two main issues:
you never reset cont so the second while loop will never do anything
even if you did that you would always skip the first Bestellung since it was already read when the second loop is reached
I would propose something along the lines of:
Object object = objectStream.readObject();
if (object instanceof AKunde) {
kundenImport.add((AKunde) object);
} else if (object instanceof Bestellung) {
bestellungenImport.add((Bestellung) object);
} else {
// something else was read
}
You simply need to loop over this code and add proper error handling where needed.
I would suggest, you change the way you write your objects to ObjectOutputStream in the first place:
Directly write the kundenListe and bestellListe objects, so you dont't have to worry about types or number of elements when reading the objects again. Your stream of object then always contains two objects, the two lists.
// use try-with-resources if you're on Java 7 or newer
try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file))) {
// write the complete list of objects
outputStream.writeObject(kundenliste);
outputStream.writeObject(bestellListe);
} catch (IOException e) {
e.printStackTrace(); //TODO proper exception handling
}
Then you could read it just like that:
ArrayList<AKunde> kundenImport = new ArrayList<>();
ArrayList<Bestellung> bestellungenImport = new ArrayList<>();
//again try-with-resources
try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file))) {
kundenImport.addAll((List) inputStream.readObject());
bestellungenImport.addAll((List) inputStream.readObject());
} catch (IOException | ClassNotFoundException e) { //multi-catch, if Java 7 or newer
e.printStackTrace(); //TODO proper exception handling
}
Further reads:
The try-with-resources Statement
Catching Multiple Exception Types (...)
cur file does not seem to be deleted and temp file does not get renamed.
private class editClassListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
File temp = new File("courseTemp.bin");
File cur = new File("course.bin");
ArrayList<Course> courses = new ArrayList<Course>();
int count = 0;
try {
FileInputStream fin = new FileInputStream(cur);
while(true)
{
try
{
ObjectInputStream oin = new ObjectInputStream(fin);
Course c = (Course) oin.readObject();
courses.add(c);
}catch (EOFException eofException){
break;
} catch (IOException e1) {
e1.printStackTrace();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
}
while(count < courses.size())
{
if(enterCourseID.getText().equals(courses.get(count).getCourseID()))
{
courses.get(count).setDescription(enterCourseDescription.getText());
courses.get(count).setSemester((String) semesterBox.getSelectedItem());
courses.get(count).setYear(yearBox.getSelectedIndex());
}
}
temp.renameTo(cur);
cur.delete();
temp.delete();
fin.close();
FileOutputStream fos = new FileOutputStream(temp);
courses.trimToSize();
count = 0;
while(count < courses.size())
{
ObjectOutputStream oop = new ObjectOutputStream(fos);
oop.writeObject(courses.get(count));
count++;
}
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
Both File.delete() and File.renameTo() do not throw an Exception but instead return false if the underlying OS-operation cannot be executed. Reasons for that are dependant on your system, but include among others:
The file you are trying to rename/delete is in use (i. e. open streams)
The file is protected by the OS (insufficient rights)
In case of renaming: A file with the new name already exists
In your case, at least the first point is true. You should be fine by simply closing your FileInputStream fin before trying to delete cur. As for the renaming, you might need to delete cur first before renaming temp.
As an aside, the Utility Class java.nio.file.Files offers methods (move()&delete()) for renaming and deleting, which throw an IOException, if the operation fails, with the cause of failure in the error message.
Whenever I run my code, the inv.txt file changes from having 25 lines of the character 1 to nothing, could someone tell me what I'm doing wrong?
PS the main class includes inventory.addItem();
public class inventory {
File inventory = new File("Resources/inv.txt");
File db = new File("Resources/db.txt");
FileWriter write;
StringBuilder writethis;
public void addItem(int item, int slot){
int i;
Scanner scan = null;
try {
scan = new Scanner(inventory);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
write = new FileWriter(inventory);
} catch (IOException e) {
e.printStackTrace();
}
for(i = 1; i < slot; i++)writethis.append(scan.nextLine());
System.out.println(writethis.toString());
}
}
Use write = new FileWriter(inventory, true);
It will append data to existing file. See the documentation on FileWriter Constructor for further details.
I'm learning now how to do serialization using Java Language. I have read some posts and docs about the subject and I tried to do a simple example (below)
public class SterializeObject implements java.io.Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
private transient int code;
public SterializeObject (String n, int c){
name = n;
code = c;
}
public void printAtributes (){
System.out.println("name: " + name + "; code: " + code);
}
}
public class MainClass {
public static void main(String[] agrs) {
SterializeObject ob1 = new SterializeObject("ana", 1);
SterializeObject ob2 = new SterializeObject("rita", 2);
try {
FileOutputStream fileOut = new FileOutputStream("file.data");
ObjectOutputStream outObj = new ObjectOutputStream(fileOut);
outObj.writeObject(ob1);
outObj.writeObject(ob2);
outObj.close();
System.out.println("Objects were serialized!");
} catch (IOException e) {
e.printStackTrace();
}
ArrayList<SterializeObject> list = new ArrayList<SterializeObject>();
try {
FileInputStream fileInput = new FileInputStream("file.data");
ObjectInputStream inputObj = new ObjectInputStream(fileInput);
Object o;
try {
while ((o = inputObj.readObject()) != null) {
list.add((SterializeObject) o);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Erro foi aqui! (1)");
}
inputObj.close();
fileInput.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Erro foi aqui! (2)");
}
for (int i = 0; i < list.size(); ++i) {
list.get(i).printAtributes();
}
}
}
I created a Class SterializeObject that implements java.io.Serializable with two variables: one string (name) and one int (code) that is transient. Then In the main I generate two instances of that class and I tried to write it in a file, that I have done successfully! After that, I try to read the two object with a Loop.. there is my problem.. since the ObjectInputStream dosen't have some kind of method to see if we are in the end or not. So, I tried to do with this condition: (o = inputObj.readObject()) != null.
My output is this:
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at MainClass.main(MainClass.java:30)
Objects were serialized!
Erro foi aqui! (2)
name: ana; code: 0
name: rita; code: 0
I get the objects, but I get an error because, I think, is trying to access to something that doesn't exist.
Someone can tell me other way to do it?
Best Regards.
Read as many objects as the number of written objects, or write the list of objects itself, instead of writing every object one after the other.
(Or rely on the EOFException to detect the end of the stream, but this is ugly).
As many of you told me to do, I created a ArrayList and serialized the ArrayList.
My code is:
public class MainClass {
public static void main(String[] agrs) {
SterializeObject ob1 = new SterializeObject("ana", 1);
SterializeObject ob2 = new SterializeObject("rita", 2);
ArrayList <SterializeObject> list = new ArrayList<>();
list.add(ob1);
list.add(ob2);
ArrayList <SterializeObject> input = new ArrayList<SterializeObject>();
try {
FileOutputStream fileOut = new FileOutputStream("file.data");
ObjectOutputStream outObj = new ObjectOutputStream(fileOut);
outObj.writeObject(list);
outObj.close();
System.out.println("Objects were serialized!");
} catch (IOException e) {
e.printStackTrace();
}
try {
FileInputStream fileInput = new FileInputStream("file.data");
ObjectInputStream inputObj = new ObjectInputStream(fileInput);
Object o;
try {
input = (ArrayList<SterializeObject>) inputObj.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Erro foi aqui! (1)");
}
inputObj.close();
fileInput.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Erro foi aqui! (2)");
}
for (int i = 0; i < input.size(); ++i) {
input.get(i).printAtributes();
}
}
}
And the output is:
Objects were serialized!
name: ana; code: 0
name: rita; code: 0
Thank you for the help!
Close the FileOutputStream also along with ObjectOutputStream
fileOut.close();
Why don't you add both object to an ArrayList, and serialize the ArrayList. Then you just have to Deserialize the ArrayList and it will be populated with both objects.
You can do this by placing the readObject call inside a try-catch block and catching that EOFException you get, signaling you have read all the objects.
Replace your while loop with this piece of code
do{
try
{
o = inputObj.readObject();
list.add((SterializeObject) o);
}
catch(EOFException e)
{
o = null;
}
}while (o != null);