Hi all I need an advice.
I'll explain my problem. I want take data from web , elaborate the result, keep it and serialize on file.
I need to restore and use data from file , somehow. I dont want that file is been overwritten and lose old data.I need have a sort of list of Object in the File where i can search the last , use Method of another class to find some values etc , insert or similar, etc.....
In this case i used ArrayList but i dont know if it was the best choise.
I tried to do this but i have a problem know. In the specific if use a Class called Data and i want a serilizate file that keep ArrayList. So when i call method save(Object obj) of FileStructureClass(a class that i made to save, load file ) in this method i need to check if file already has an ArrayList so if it's true i can add in that Arraylist the Object , passed as parameter , else i return a new ArrayList. Of course i do a cast from Object to Data Class when i add in ArrayList.
I would fix this problem and then after find a better solution (if there is) to my problem.
The Data Class contains only 3 String and 1 GregoriusCalendar. Keep in mind(for the choise as ArrayList as Solution) that i need save file 1 time at day(i do a check with last element of the arraylist and do check with actual GregoriusCalendar..if past 1 day i can insert the element in arraylist).
After Explain the situation i list my problems
When i try to save for the FIRST time a Data Object in the Arraylist i have an error java.io.EOFException , i think that the problem is in tmp= ArrayList)ois.readObject(); but i cant find a solution. Dont happen when i insert manually a DataObject in the ArrayList and i use a method to insert a second one
According to you , ArrayList is a valid solution for my situation?
This method check if the file has data or not.
If it's empty i create a new one ArrayList and return it
otherwise i read the ArrayList already store in the file , and i return it
public ArrayList<Dati> check() {
ArrayList<Dati> tmp = new ArrayList<Dati>();
ObjectInputStream ois;
try{
fileInput = new FileInputStream("prova.dat");
ois = new ObjectInputStream(fileInput);
if (ois.readObject() == null) {
Logger.getLogger("file is empty");
ois.close();
return tmp;
}
//The error that i recive arrives from the under line
// (Impossible load file check method: java.io.EOFException
tmp = (ArrayList<Dati>) ois.readObject();
ois.close();
} catch (IOException e) {
System.out.println("Impossibile caricare i dati metodo check: "+e);
}
catch (ClassNotFoundException e) {
System.err.println("error");
}
return tmp;
}
//This method recive data of file that contains ArrayList<Data>
// and add to this a Data Object gave as Parameter
public void save(Object obj){
try{
ArrayList<Data> temp = check();
temp.add((Data) obj);
ObjectOutputStream os =
new ObjectOutputStream(new FileOutputStream("prova.dat"));
os.writeObject(temp);
os.flush();
os.close();
}
catch(IOException e){
System.out.println("Impossible save datas: "+e);
}
}
public Object load(String path){
Object obj=null;
try{
fileInput=new FileInputStream(path);
ois=new ObjectInputStream(fileInput);
obj=ois.readObject();
ois.close();
}
catch(IOException e){
System.out.println("Impossible load file: "+e);
}
catch(ClassNotFoundException e){
System.err.println();
}
return obj;
}
When i try to save for the FIRST time a Data Object in the Arraylist
i have an error java.io.EOFException , i think that the problem is
in tmp= (ArrayList)ois.readObject(); but i cant find a solution. Dont
happen when i insert manually a DataObject in the ArrayList and i
use a method to insert a second one
This seems to be correct. Looking at javadoc, it does seem like ois.readObject() returns null when there is nothing in the file. One approach I can think of is to initialize the file with an empty ArrayList in setup phase.
According to you , ArrayList is a valid solution for my situation?
I don't see why not. But it depends on what you will do with the list after reading it. If you have to search it often and it is large then you may consider a different data structure.
Related
I am given an assignment where we are not allowed to use a DB or libraries but only textfile for data storage.
But it has rather complex requirements, for e.g. many validations, because of that, we need to "access the db" (i.e. read the textfile) many times.
My question is: should I create a class like this:
class SomeRepository{
static ArrayList<Users> users = new ArrayList();
public SomeRepository(){
//instantiate this class on program load
//In constructor, we read the text file, instantiate and store everything inside the arraylist.
}
//public getOneUser(){ // for get methods, we don't read from text file at all }
/public save() { //text file saving code overhere }
}
Is this a good approach to solve the above problem? Currently, what we are doing is reading and writing to the text file every time we want to retrieve some data or write something new.
Wouldn't this be too expensive in terms of heap space memory? Or should I just read/write to the text file for every method?
public class IOManager {
public static void writeObjToTxtFile(String fileName, Object object) {
File file = new File(fileName + ".txt");//File will be created in the root directory where the program runs.
try (FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);) {
oos.writeObject(object);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Object readObjFromTxtFile(String fileName) {
Object obj = null;
File file = new File(fileName + ".txt");
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
obj = ois.readObject();
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
return obj;
}
}
Add this class to your project. Since it's general for all Objects, you can pass and receive Objects like these as well: ArrayList<Users>. Play around and Tinker with it to fit whatever your specific purpose is. Hint: You can write other custom methods that calls these methods. eg:
public static void writeUsersToFile(ArrayList<Users> usersArrayList){
writeObjToTxtFile("users",usersArrayList);
}
Ps. Make sure your Objects implement Serializable. Eg:
public class Users implements Serializable {
}
I would suggest reading the contents of your file to a dynamic list such as an arraylist at the start of your program. Make the required queries/changes to your arraylist and then write that arraylist to your file when the program is set to close. This will save significant time over repeated file reads/writes.
This isn't without it's drawbacks, though. You don't want to hogg up memory in case of very large files - but considering this is an assignment, that may not be the case. Additionally, should your program terminate prior to the write at the end, all changes made to your database during the current execution will be lost.
I've spent all day on this and need some advice!
I'm trying to save the contents of a Array List into a text file.
I have got android to save the array list contents to an internal *.txt however after entering "Test one" and "Test Two" into the array list, and a button is clicked to save the current contents into the text file. I get the following:
�� sr java.util.ArrayListx����a� I sizexp w t Test Onet Test Twox
An Error is also given which is:
"File was loaded in the wrong encoding:'UTF-8'
The System.out.print gives the results:
"I/System.out: [Test One, Test Two]"
which is accurate to show the contents of the array list.
Code used:
public void savingfile() {
read = (Button)findViewById(R.id.read);
read.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
outputStream = openFileOutput(anxfile, Context.MODE_PRIVATE);
ObjectOutputStream out = new ObjectOutputStream(outputStream);
out.writeObject(arrayList);
System.out.println(arrayList);
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
Many thanks, Leon
P.S. I have tried many youtube tutorials/Stackoverflow answers to fix the problem but still having the same issue
The list contains Strings, right?
If so, then instead of writing the object into your stream:
out.writeObject(arrayList);
You may want to dig out the Strings from the List first and write them:
for (String text : arrayList) {
out.writeObject(text);
}
I am writing a small program to help with planning future workouts. I am nearly finished however saving and loading is giving me some trouble. The program works with a list of "ride"(a custom class) objects that hold a number of qualities (like a Dat, and then some ints and doubles)
right now, I have two methods, a "saver" and a "loader":
public void saver() {
try{ // Catch errors in I/O if necessary.
// Open a file to write to, named SavedObj.sav.
FileOutputStream saveFile=new FileOutputStream("SaveObj.sav");
// Create an ObjectOutputStream to put objects into save file.
ObjectOutputStream save = new ObjectOutputStream(saveFile);
// Now we do the save.
for (int x = 0; x < rides.size(); x++) {
save.writeObject(rides.get(x).getDate());
save.writeObject(rides.get(x).getMinutes());
save.writeObject(0);
save.writeObject(rides.get(x).getIF());
save.writeObject(rides.get(x).getTss());
}
// Close the file.
save.close(); // This also closes saveFile.
}
catch(Exception exc){
exc.printStackTrace(); // If there was an error, print the info.
}
}
public void loader() {
try{
// Open file to read from, named SavedObj.sav.
FileInputStream saveFile = new FileInputStream("SaveObj.sav");
// Create an ObjectInputStream to get objects from save file.
ObjectInputStream save = new ObjectInputStream(saveFile);
Ride worker;
while(save.available() > 0) {
worker = new Ride((Date)save.readObject(), (int)save.readObject(), (double)save.readObject(), (double)save.readObject(), (int)save.readObject());
addRide(worker.getDate(), worker.getMinutes(), 0, worker.getIF(), worker.getTss());
}
// Close the file.
save.close(); // This also closes saveFile.
}
catch(Exception exc){
exc.printStackTrace(); // If there was an error, print the info.
}
}
When I run the program, neither "save" nor "load" return any errors. A .sav file is created when one does not exist, and is edited each time the program is executed. Yet, the program never restores data from previous sessions. Please let me know if more information is required.
Thanks in advance for the help!
Don't use available() which returns the number of bytes that can be read without blocking. It doesn't mean what all bytes were read.
If your objects are never null, you could use Object readObject() to check if all data were read from the inputstream.
Date date = null;
while( (date = (Date)save.readObject()) != null) {
worker = new Ride(date, (int)save.readObject(), (double)save.readObject(), (double)save.readObject(), (int)save.readObject());
addRide(worker.getDate(), worker.getMinutes(), 0, worker.getIF(), worker.getTss());
}
Otherwise if read values may be null, you could serialize directly the Ride object or a class containing all fields to serialize rather than unitary fields which could be null With this, the check to know if all data were read with Object readObject() could work.
Do not use available() as a condition. It just tells you whether there is some byte available for immediate reading without any delay, it does not mean the stream has reached its end.
Also you should maybe add a BufferedInputStream and BufferedOutputStream between the Object and File streams, that's almost always a good idea.
To solve your issue you could e. g. first write an integer in the save method that tells you how many objects are in the file and on load read that integer and then make a simple for loop with this amount.
Or you could throw in a PushbackInputStream in the row and then as EOF check use its read() method. It will return -1 on EOF and you can abort reading. If it returns anything else, you unread() the read byte and use the ObjectInputStream that you placed on top.
Before I proceed to my question : please note that I am not working on any client-server application that would require serialization, but the program I am trying to customize stores one big instance of one big class in a .dat file. I have read about this issue (memory leak in ObjectOutputStream and ObjectInputStream)and the fact that I could probably need to :
use the ObjectOutputStream.reset() method after writing the class instance in the .dat file, so that it doesn't hold the reference anymore;
re-write the code without using serialization;
split the file and read it in chunks;
change the JVM memory parameter by using -Xmx;
So, I was provided with one class that generates a language model and saves it with a .dat extension; the code was probably optimized for small model files (there are 2 model files provided as examples, both around 10MB ), but I generated a much larger model class, and it is around 40MB. Then, there is another class in another folder, totally independent on the first one, that uses this model, and the model has to be loaded using ObjectInputStream. Here comes the problem : a classic "OutOfMemoryError : Java heap space".
Writing the object:
try {
// Create an output stream to the file.
FileOutputStream file_output = new FileOutputStream (file);
ObjectOutputStream o = new ObjectOutputStream( file_output );
o.writeObject(this);
file_output.close ();
}
catch (IOException e) {
System.err.println ("IO exception = " + e );
}
Reading the object:
InputStream model = null;
ModelGeneration oRead = null;
ObjectInputStream p = null;
try {
model = new FileInputStream(filename);
BufferedInputStream buf = new BufferedInputStream(model);
p = new ObjectInputStream(buf);
oRead = (ModelGeneration) p.readObject();
p.reset();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
model.close();
} catch (Exception e) {
e.printStackTrace();
}
}
I tried to use the reset() method, but it is useless because we load only one instance of one class at a time, nothing else needed. This is why I can't split the file, too: only one class instance is stored in the .dat file.
Changing the heap space seems like a worse solution than optimizing the code.
I would really appreciate your advice on what I can do.
Btw the code is here : http://svn.apache.org/repos/asf/uima/addons/trunk/Tagger/, I only implemented the required classes for a different language.
P.S. Works fine if I create a smaller model, but I would prefer the bigger one.
I'm working on an Android app and I got to a point where I need to add some Store objects to an ArrayList favoriteStores. The problem is that I want this list to persist after closing the application, because my list of favorite stores must stay there until I chose to delete particular items inside it. Anyone got any idea what type of implementation I might use? Thanks in advance,
If you don't want to save arraylist to database, you can save it to file. It is a great way if you just want to save arraylist and don't want to touch sqlite.
You can save arraylist to file with this method
public static <E> void SaveArrayListToSD(Context mContext, String filename, ArrayList<E> list){
try {
FileOutputStream fos = mContext.openFileOutput(filename + ".dat", mContext.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(list);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
And you can read that saved file to arraylist with this method
public static Object ReadArrayListFromSD(Context mContext,String filename){
try {
FileInputStream fis = mContext.openFileInput(filename + ".dat");
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj= (Object) ois.readObject();
fis.close();
return obj;
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<Object>();
}
}
Hope this help.
You can either use a database like SQLite (howto here) or use some serialization technique. There is a related question to serialization here.
General information about storing data in Android can be found here.
Here's a nice post about data storage options in Android, read it carefully and select the option that you find the most appropriate.