Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 months ago.
Improve this question
How can i fix problem with load ArrayList from file?
Full code is on the git:
project github link
When I load data from file I'll get it back -> IOException
I'm learning to use the stream so I'm writing it to a file.
After the end of the program, I want to write the time the user has reached in the arraylist and list all the times with which the game was finished.
package sk.games.puzzle;
import java.io.*;
import java.util.*;
public class BestTimes implements Iterable<BestTimes.PlayerTime>, Serializable{
private static final String BESTTIME_DB = System.getProperty("user.home")
+ System.getProperty("file.separator")
+ "best.time";
private List<PlayerTime> playerTimes = new ArrayList<>();
public Iterator<PlayerTime> iterator() {
return playerTimes.iterator();
}
public void addTime(String name, int time){
playerTimes.add(new PlayerTime(name, time));
Collections.sort(playerTimes);
}
public void load(){
ObjectInputStream load = null;
try {
load = new ObjectInputStream(new FileInputStream(BESTTIME_DB));
playerTimes = (ArrayList<PlayerTime>) load.readObject();
} catch (FileNotFoundException e) {
System.err.println("fail nebola najdena db");
} catch (IOException e) {
System.err.println("fail nebola otvorena db");
} catch (ClassNotFoundException e) {
System.err.println("fail nebol najdeny zaznam");
} finally {
if (load != null) {
try {
load.close();
} catch (IOException e) {
//empty
}
}
}
}
public void save() {
ObjectOutputStream save = null;
try {
save = new ObjectOutputStream(new FileOutputStream(BESTTIME_DB));
save.writeObject(playerTimes);
} catch (FileNotFoundException e) {
System.err.println("fail db neexistuje");
} catch (IOException e) {
System.err.println("fail nepodarilo sa otvorit db");
} finally {
if (save != null) {
try {
save.close();
} catch (IOException e) {
//empty
}
}
}
}
#Override
public String toString() {
Formatter f = new Formatter();
for (int i = 0; i < playerTimes.size(); i++) {
PlayerTime pt = playerTimes.get(i);
f.format("%02d. %s - %ds.\n", i, pt.getName(), pt.getTime());
}
return f.toString();
}
public static class PlayerTime implements Comparable<PlayerTime> {
private final String name;
private final int time;
public PlayerTime(String name, int time) {
this.name = name;
this.time = time;
}
public String getName() {
return name;
}
public int getTime() {
return time;
}
#Override
public int compareTo(PlayerTime o){
return Integer.compare(this.time, o.getTime());
}
}
}
The problem is that your PlayerTime class is not serializable.
public static class PlayerTime implements Comparable<PlayerTime> { }
should be
public static class PlayerTime implements Comparable<PlayerTime> implements Serializable { }
It's not necessary to make BestTimes serializable unless you do write BestTimes object to file.
Related
I'm execising with Object I/O and have made a very simple class(Thing) which only has one attribute(int weight)
I am getting a notSerializable exception and I really don't get it.
The Thing Class:
import java.io.Serializable;
public class Thing implements Comparable<Thing>, Serializable{
private static final long serialVersionUID = 1L;
private int weight;
public Thing(int weight) {
this.weight = weight;
}
public Thing(){
this((int)(Math.random()*1000));
}
public int getWeight() {
return weight;
}
#Override
public int compareTo(Thing o) {
return this.weight - o.weight;
}
}
My Saver class:
public class Saver {
private FileOutputStream fos;
private ObjectOutputStream oos;
private File file;
public Saver() {
file = new File("src/dataSaverReader/things.data");
}
public void saveArrayToFile(Thing[] array) {
try {
fos = new FileOutputStream(file);
oos = new ObjectOutputStream(fos);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
for (Thing element : array) {
try {
oos.writeObject(element);
} catch (IOException e) {
e.printStackTrace();
}
}
try {
oos.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Exception Details:
java.io.NotSerializableException: methods.Thing
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at dataSaverReader.Saver.saveArrayToFile(Saver.java:32)
at methods.Root.go(Root.java:48)
at methods.Root.main(Root.java:17)
This question already has answers here:
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException
(2 answers)
Closed 6 years ago.
I am trying to read all objects from the file. Below is the snippet of the method use to fetch list of object from file.
public List displayParties() {
ObjectInputStream ois = null;
List<RegisterParty> results = new ArrayList();
try {
FileInputStream fis = new FileInputStream("/media/user/disk2/myapp/assignment/party.ser");
ois = new ObjectInputStream(fis);
while (true) {
System.out.println(" inside while true");
results.add((RegisterParty) ois.readObject());
System.out.println(results);
}
} catch (IOException ex) {
ex.printStackTrace();
}
catch (Exception ex){
ex.printStackTrace();
} finally{
try {
ois.close();
}catch (IOException ex){
ex.printStackTrace();
}
}
return results;
}
RegisterParty Class :
public class RegisterParty implements Serializable {
String bookingPersonName;
String childName;
String childAge;
String theme;
String foodAlergies;
String noOfGuest;
String specialGuest;
public String getBookingPersonName() {
return bookingPersonName;
}
public void setBookingPersonName(String bookingPersonName) {
this.bookingPersonName = bookingPersonName;
}
public String getChildName() {
return childName;
}
public void setChildName(String childName) {
this.childName = childName;
}
public String getChildAge() {
return childAge;
}
public void setChildAge(String childAge) {
this.childAge = childAge;
}
public String getTheme() {
return theme;
}
public void setTheme(String theme) {
this.theme = theme;
}
public String getFoodAlergies() {
return foodAlergies;
}
public void setFoodAlergies(String foodAlergies) {
this.foodAlergies = foodAlergies;
}
public String getNoOfGuest() {
return noOfGuest;
}
public void setNoOfGuest(String noOfGuest) {
this.noOfGuest = noOfGuest;
}
public String getSpecialGuest() {
return specialGuest;
}
public void setSpecialGuest(String specialGuest) {
this.specialGuest = specialGuest;
}
public String toString(){
return bookingPersonName+" "+childName+" "
+childAge+" "+foodAlergies+" "+theme+" "+noOfGuest+" "+specialGuest;
}
}
But getting the below exception :
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: models.RegisterParty
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1354)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at helper.HelperFunctions.displayParties(HelperFunctions.java:39)
at services.PartyOperations.listAllParties(PartyOperations.java:64)
at assignment.App.main(App.java:34)
at helper.HelperFunctions.saveParty(HelperFunctions.java:24)
at services.PartyOperations.registerParty(PartyOperations.java:53)
at assignment.App.main(App.java:28)
Caused by: java.io.NotSerializableException: models.RegisterParty
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
at helper.HelperFunctions.saveParty(HelperFunctions.java:20)
at services.PartyOperations.registerParty(PartyOperations.java:52)
... 1 more
RegisterParty implements the serializable interface. Its a menu based app, so when i save the object in file, its save successfully. But call the method to get all object in list, its throw the exception. Any Idea why?
This method successfully execute to serialize the object:
public void saveParty(RegisterParty registerParty){
try {
FileOutputStream fout = new FileOutputStream("/media/user/disk2/myapp/assignment/party.txt");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(registerParty);
oos.close();
System.out.println("Successfull Register");
System.out.println("========Select you choice========");
App.main(str);
}
catch (Exception ex){
ex.printStackTrace();
}
}
When I implement a Serializable object I add a static variable serialVersionUID to the class:
private static final long serialVersionUID = -1892561327013038124L;
This line gets added as a suggestion by either the eclipse or android studio. I don't know how to do it with IntelliJIdea.
It worth a try! I believe this ID used for deserialisation.
There was conflict in fileToRead & fileToWrite.
FileInputStream fis = new FileInputStream("/media/user/disk2/myapp/assignment/party.ser");
FileOutputStream fout = new FileOutputStream("/media/user/disk2/myapp/assignment/party.txt");
I´ve been reading that the static fields are not serialized but, after testing it, I saw that´s not true.
The static modifier even overrides the transient modifier and makes the field serializable.
I write one example from a book that shows that a static transient field is serialized.
import java.io.*;
class USPresident implements Serializable {
private static final long serialVersionUID = 1L;
#Override
public String toString() {
return "US President [name=" + name
+ ", period=" + period + ", term=" + term + "]";
}
public USPresident(String name, String period, String term) {
this.name = name;
this.period = period;
this.term = term;
}
private String name;
private String period;
private static transient String term;
}
class TransientSerialization {
public static void main(String[] args) {
USPresident usPresident = new USPresident("Barack Obama", "2009 to --", "56th term");
System.out.println(usPresident);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("USPresident.data"))) {
oos.writeObject(usPresident);
} catch (IOException ioe) {
// ignore
}
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("USPresident.data"))) {
Object obj = ois.readObject();
if (obj != null && obj instanceof USPresident) {
USPresident presidentOfUS = (USPresident) obj;
System.out.println(presidentOfUS);
}
} catch (IOException ioe) {
// ignore
} catch (ClassNotFoundException e) {
// ignore
}
}
}
Is wrong the general concept that static fields are not serialized? Is it just a recommendation?
Why the transient modifier doen't take effect with static ?
note: I understand that initialize a static field in a constructor is an odd code, but the compiler let me do it and it's just in order to understand static fields serialization.
This has nothing to do with serialization but due to the fact that you are setting the static field when you create your usPresident variable. This sets the field for the class of that JVM. Try reading in the serialized president in a different program and see that the transient field is not serialized.
As an aside: consider not ignoring your exceptions.
For example, refactored, your code could look like this:
class USPresident implements Serializable {
private static final long serialVersionUID = 1L;
#Override
public String toString() {
return "US President [name=" + name + ", period=" + period + ", term="
+ term + "]";
}
public USPresident(String name, String period, String term) {
this.name = name;
this.period = period;
this.term = term;
}
private String name;
private String period;
private static transient String term;
}
class TransientSerialization {
public static void main(String[] args) {
serializePresident();
deserializePresident();
}
private static void deserializePresident() {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(
"USPresident.data"));
Object obj = ois.readObject();
if (obj != null && obj instanceof USPresident) {
USPresident presidentOfUS = (USPresident) obj;
System.out.println(presidentOfUS);
}
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void serializePresident() {
USPresident usPresident = new USPresident("Barack Obama", "2009 to --",
"56th term");
System.out.println(usPresident);
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("USPresident.data"));
oos.writeObject(usPresident);
oos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
The second time your run it, change the main method to:
public static void main(String[] args) {
// serializePresident();
deserializePresident();
}
And see what comes up.
For me, the first run returns:
US President [name=Barack Obama, period=2009 to --, term=56th term]
US President [name=Barack Obama, period=2009 to --, term=56th term]
and the second run returns:
US President [name=Barack Obama, period=2009 to --, term=null]
I have a program that performs lots of calculations and reports them to a file frequently. I know that frequent write operations can slow a program down a lot, so to avoid it I'd like to have a second thread dedicated to the writing operations.
Right now I'm doing it with this class I wrote (the impatient can skip to the end of the question):
public class ParallelWriter implements Runnable {
private File file;
private BlockingQueue<Item> q;
private int indentation;
public ParallelWriter( File f ){
file = f;
q = new LinkedBlockingQueue<Item>();
indentation = 0;
}
public ParallelWriter append( CharSequence str ){
try {
CharSeqItem item = new CharSeqItem();
item.content = str;
item.type = ItemType.CHARSEQ;
q.put(item);
return this;
} catch (InterruptedException ex) {
throw new RuntimeException( ex );
}
}
public ParallelWriter newLine(){
try {
Item item = new Item();
item.type = ItemType.NEWLINE;
q.put(item);
return this;
} catch (InterruptedException ex) {
throw new RuntimeException( ex );
}
}
public void setIndent(int indentation) {
try{
IndentCommand item = new IndentCommand();
item.type = ItemType.INDENT;
item.indent = indentation;
q.put(item);
} catch (InterruptedException ex) {
throw new RuntimeException( ex );
}
}
public void end(){
try {
Item item = new Item();
item.type = ItemType.POISON;
q.put(item);
} catch (InterruptedException ex) {
throw new RuntimeException( ex );
}
}
public void run() {
BufferedWriter out = null;
Item item = null;
try{
out = new BufferedWriter( new FileWriter( file ) );
while( (item = q.take()).type != ItemType.POISON ){
switch( item.type ){
case NEWLINE:
out.newLine();
for( int i = 0; i < indentation; i++ )
out.append(" ");
break;
case INDENT:
indentation = ((IndentCommand)item).indent;
break;
case CHARSEQ:
out.append( ((CharSeqItem)item).content );
}
}
} catch (InterruptedException ex){
throw new RuntimeException( ex );
} catch (IOException ex) {
throw new RuntimeException( ex );
} finally {
if( out != null ) try {
out.close();
} catch (IOException ex) {
throw new RuntimeException( ex );
}
}
}
private enum ItemType {
CHARSEQ, NEWLINE, INDENT, POISON;
}
private static class Item {
ItemType type;
}
private static class CharSeqItem extends Item {
CharSequence content;
}
private static class IndentCommand extends Item {
int indent;
}
}
And then I use it by doing:
ParallelWriter w = new ParallelWriter( myFile );
new Thread(w).start();
/// Lots of
w.append(" things ").newLine();
w.setIndent(2);
w.newLine().append(" more things ");
/// and finally
w.end();
While this works perfectly well, I'm wondering:
Is there a better way to accomplish this?
Your basic approach looks fine. I would structure the code as follows:
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public interface FileWriter {
FileWriter append(CharSequence seq);
FileWriter indent(int indent);
void close();
}
class AsyncFileWriter implements FileWriter, Runnable {
private final File file;
private final Writer out;
private final BlockingQueue<Item> queue = new LinkedBlockingQueue<Item>();
private volatile boolean started = false;
private volatile boolean stopped = false;
public AsyncFileWriter(File file) throws IOException {
this.file = file;
this.out = new BufferedWriter(new java.io.FileWriter(file));
}
public FileWriter append(CharSequence seq) {
if (!started) {
throw new IllegalStateException("open() call expected before append()");
}
try {
queue.put(new CharSeqItem(seq));
} catch (InterruptedException ignored) {
}
return this;
}
public FileWriter indent(int indent) {
if (!started) {
throw new IllegalStateException("open() call expected before append()");
}
try {
queue.put(new IndentItem(indent));
} catch (InterruptedException ignored) {
}
return this;
}
public void open() {
this.started = true;
new Thread(this).start();
}
public void run() {
while (!stopped) {
try {
Item item = queue.poll(100, TimeUnit.MICROSECONDS);
if (item != null) {
try {
item.write(out);
} catch (IOException logme) {
}
}
} catch (InterruptedException e) {
}
}
try {
out.close();
} catch (IOException ignore) {
}
}
public void close() {
this.stopped = true;
}
private static interface Item {
void write(Writer out) throws IOException;
}
private static class CharSeqItem implements Item {
private final CharSequence sequence;
public CharSeqItem(CharSequence sequence) {
this.sequence = sequence;
}
public void write(Writer out) throws IOException {
out.append(sequence);
}
}
private static class IndentItem implements Item {
private final int indent;
public IndentItem(int indent) {
this.indent = indent;
}
public void write(Writer out) throws IOException {
for (int i = 0; i < indent; i++) {
out.append(" ");
}
}
}
}
If you do not want to write in a separate thread (maybe in a test?), you can have an implementation of FileWriter which calls append on the Writer in the caller thread.
One good way to exchange data with a single consumer thread is to use an Exchanger.
You could use a StringBuilder or ByteBuffer as the buffer to exchange with the background thread. The latency incurred can be around 1 micro-second, doesn't involve creating any objects and which is lower using a BlockingQueue.
From the example which I think is worth repeating here.
class FillAndEmpty {
Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
DataBuffer initialEmptyBuffer = ... a made-up type
DataBuffer initialFullBuffer = ...
class FillingLoop implements Runnable {
public void run() {
DataBuffer currentBuffer = initialEmptyBuffer;
try {
while (currentBuffer != null) {
addToBuffer(currentBuffer);
if (currentBuffer.isFull())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) { ... handle ... }
}
}
class EmptyingLoop implements Runnable {
public void run() {
DataBuffer currentBuffer = initialFullBuffer;
try {
while (currentBuffer != null) {
takeFromBuffer(currentBuffer);
if (currentBuffer.isEmpty())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) { ... handle ...}
}
}
void start() {
new Thread(new FillingLoop()).start();
new Thread(new EmptyingLoop()).start();
}
}
Using a LinkedBlockingQueue is a pretty good idea. Not sure I like some of the style of the code... but the principle seems sound.
I would maybe add a capacity to the LinkedBlockingQueue equal to a certain % of your total memory.. say 10,000 items.. this way if your writing is going too slow, your worker threads won't keep adding more work until the heap is blown.
I know that frequent write operations
can slow a program down a lot
Probably not as much as you think, provided you use buffering.
When Im trying to read an object and store in arraylist but im getting an exception this is the part of code where im facing a problem.
public class Customer implements Serializable {
private String username;
private String password;
private int age;
private String accttype;
private String acctno;
private float amount;
Customer() {
System.out.println("Im in Customer");
}
public boolean writeToDataBase(String uname, String pwd, int cage, String caccttype, String cacctno, float camount) throws IOException {
Customer custobj = new Customer();
FileOutputStream fos=null;
ObjectOutputStream oos=null;
custobj.username = uname;
custobj.password = pwd;
custobj.age = cage;
custobj.accttype = caccttype;
custobj.acctno = cacctno;
custobj.amount = camount;
try {
fos=new FileOutputStream("Customerdetails.txt",true);
oos=new ObjectOutputStream(fos);
oos.writeObject(custobj);
oos.close();
fos.close();
return true;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
finally
{
fos.close();
oos.close();
}
}
public boolean retriveFromDataBase(int a) throws IOException
{
try {
Customer custobj = new Customer();
FileInputStream fis=null;
ObjectInputStream ois=null;
ArrayList<Customer> custlist;
try {
custlist = new ArrayList<Customer>();
fis = new FileInputStream("Customerdetails.txt");
ois = new ObjectInputStream(fis);
while (fis.available()!=0) {
custobj=(Customer)ois.readObject();
custlist.add(custobj);
}
System.out.println("Customer List" + custlist.size());
if (a == 3) {
for (int i = 0; i < custlist.size(); i++) {
custobj = custlist.get(i);
custobj.displayCustomers();
}
}
return true;
} catch (Exception ex) {
System.out.println(ex.toString());
System.out.println("No users are presnt in the file");
return false;
}
finally
{
ois.close();
fis.close();
}
}
catch(Exception ex)
{
System.out.println(ex.toString());
return false;
}
}
public void displayCustomers()
{
try
{
System.out.println("details"+username+"\t"+age+"\t"+password+"\t"+acctno+"\t"+accttype+"\t"+amount);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
Does your object implement the Serializiable or Externalizeable interface? If yes do you use non transitive objects that don't implement serializiable/externalizeable and don't offer a argumentless default constructor?
Without further information (which exception, more code) it's hard to say.
I noted that the program throws java.io.StreamCorruptedException, when you run it for the second time. It works fine when you run it only once.
The problem is that you cannot APPEND to the same file : Customerdetails.txt every time you serialize in writeToDatabase(..) method. So remove the append flag : "true" in the call to constructor of FileOutputStream in writeToDatabase(..) method.