I'm trying do something like that:
Person; PersonList (ArrayList) contains Person;
Summary contains PersonList;
SummaryList (ArrayList) contains Summary.
Next I want to modify my Person and save it to file, like in code below:
//first run
personList.addPerson(); // PersonArrayList: [Person: Anonymous Person]
summaryList.addSummary(personList); // SummaryArrayList: [Summary: Test, PersonArrayList: [Person: Anonymous Person]]
modifyPerson(personList); // set lastName to ModifiedPerson
// PersonArrayList: [Person: Anonymous ModifiedPerson]
// SummaryArrayList: [Summary: Test, PersonArrayList: [Person: Anonymous ModifiedPerson]]
save.savePersonListToDatabase(personList);
save.saveSummaryToDatabase(summaryList);
/*
here is OK. Is one instance of PersonList and one instance of Person. Change in Person affect to both Lists.
end of first run
*/
Next I want to read it from file. I use this code to read from file (and similar to save):
public Object readObjectFromFile(String filePath) throws IOException, ClassNotFoundException {
fileInputStream = new FileInputStream(filePath);
objectInputStream = new ObjectInputStream(fileInputStream);
Object object = objectInputStream.readObject();
System.out.println("Read " + filePath + " is OK");
objectInputStream.close();
return object;
}
public PersonList readPersonListFromDatabase() {
try{
String personFilePath = "PersonList.obj";
personList = (PersonList) readObjectFromFile(personFilePath);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return personList;
}
and second run:
//second run
personList = read.readPersonListFromDatabase();
summaryList = read.readSummaryListFromDatabase();
/*
here is NOT ok. There are two instances of PersonList and two instances of Person. Change in Person does
not affect on SummaryList (because there are different instances of it)
*/
I use Serializable and FileOutputStream / ObjectOutputStream to save it.
I want to run program, do my things, save it all and close. In next run I want to read it all from files.
What should I do, if I want to keep all references after read from file?
Finally, I found the solution.
Follow to this post https://stackoverflow.com/a/10374665/14558334
I create a "container" class which looks like that:
public class ClassContainer implements Serializable {
private SummaryList summaryList;
private PersonList personList;
public ClassContainer(SummaryList summaryList, PersonList personList) {
this.summaryList = summaryList;
this.personList = personList;
}
}
Thanks to this I save / read only one object with every references saved.
Maybe it's not the best solution, but it works fine.
Related
After searching for an answer for hours I decided to ask it here, since the solutions I found didn't work.
I have a simple GUI to register a persons first/last name and date of birth. After entering the values, the data is listed in a JList. Now I want to save the data from the JList into a Txt file. But I can't find a way to get the data from the JList.
public void save(){
try(BufferedWriter bw = new BufferedWriter(new FileWriter("jlist.txt")))
{
/* Here should be the part, where I get the data from the JList */
bw.write(person.getNachname() + " ; " + person.getVorname() + " ; " + person.getDate() + "\n");
} catch (Exception speichern) {
speichern.printStackTrace();
}
}
Later I want to take the created Txt file and load it back into the same JList.
Maybe there is even a better way to do this but I haven't found something.
Some tips would be helpful :)
There is no JList method that does this for you.
You need to get the data from the ListModel.
You get the ListModel from the JList using the getModel() method.
You need to write a loop to:
get each element from the ListModel using the getElementAt(...) method.
convert the element to a String and write the data to your file.
Some tips would be helpful
Not related to your question, but typically data like this would be displayed in a JTable. Then you have a separate column for each of the first name, last name and date. Read the section from the Swing tutorial on How to Use Tables for more information.
As camickr point out there is no method implemented for what you a trying to achieve, instead there is a combination of things that you could do for archiving your goal.
You are facing the problem of data persistence. In now-a-days for small|medium|big size industrial applications the recommended approach is to relay on databases. I guess that is out the scope for one person that is starting to code, so using files for storing info is OK but is not straightforward.
In your case, if your application is for non-commercial purposes I would suggest to use the default mechanism for serializing and deserializing objects that comes bundled with the platform. With this you could write an entire object (including its data, a.k.a. its state) to a file on a disk, and later retrieve it with few lines codes. There are details about how the object gets serialize ("translate object to bits") and deserialized ("translate bits to object") that doesn't comes into place right now, but is well to advice to study them in the future if you planning to use this method in a commercial application.
So I suggest that you load and store the information of your application on start-up and shutdown respectively, thus only one load and store per application instance, while the application is active work with the data on memory. THIS is the simplest approach you could have in any application, and for that reason I suggest to start with this ideal scenario.
So, I say a lot of things but let's goes to the code that shows an example of storing (serialize) and loading (deserialize)
import java.io.*;
import java.util.*;
class Person implements Serializable {
String name;
int birthDate;
public Person(String name, int birthDate) {
this.name = name;
this.birthDate = birthDate;
}
}
class Main {
public static void main(String[] args) {
Collection<Person> collection = createExampleCollection();
System.out.println(collection);
storeCollection(collection, "persons.data");
Collection<Person> otherCollection = loadCollection("persons.data");
System.out.println(otherCollection);
}
private static Collection<Person> createExampleCollection() {
Collection<Person> collection = new ArrayList<Person>();
collection.add(new Person("p1",0));
collection.add(new Person("p2",10));
collection.add(new Person("p2",20));
return collection;
}
// here I'm doing two separated things that could gone in separate functions, 1) I'm converting into bytes and object of an specific class, 2) saving those bytes into a file on the disk. The thing is that the platform offers us convenient objects to do this work easily
private static void storeCollection(Collection<Person> collection, String filename) {
try {
FileOutputStream fos = new FileOutputStream(filename);
ObjectOutputStream out = new ObjectOutputStream(fos);
out.writeObject(collection);
out.close();
fos.close();
} catch (IOException i) {
i.printStackTrace();
}
}
// again there two things going on inside, 1) loading bytes from disk 2) converting those bits into a object of a specific class.
private static Collection<Person> loadCollection(String filename) {
try {
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream in = new ObjectInputStream(fis);
Collection<Person> persons = (Collection<Person>) in.readObject();
in.close();
fis.close();
return persons;
} catch (Exception i) {
i.printStackTrace();
return null;
}
}
}
You should try to use the functions of loadCollection and storeCollection on start-up and shutdown respectively.
I made this code with comments for jButton and jList in jFrame, Button saves text Items to File from jList.
private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) { //jButton name: "btnSave"
try { //trying to save file
BufferedWriter bw = new BufferedWriter(new FileWriter("data.txt")); //file where I store the data of jList1 (file will be stored at: C:\Users\%username%\Documents\NetBeansProjects\<ThisProjectName>\data.txt) (if You use NetBeans)
for (int i=0; i<jList1.getModel().getSize(); i++){ //opens a cycle to automatically store data of all items
bw.write(jList1.getModel().getElementAt(i)); //writing a line from jList1
bw.newLine(); //making a new line for the next item (by removing this line, You will write only one line of all items in file)
} //cycle closes
bw.close(); //file writing closes
} catch (IOException ex) { //catching the error when file is not saved
Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex); //showing the error
} //Exception closes
} //Action closes
I am writing a program that uses Serialization to store the program's objects (users, admins, books, etc). I have multiple controllers that control the adding of different objects to different array lists.
Example:
Login controller controls the adding and removing of users to the system
Example:
Book controller which controls adding and removing of books to the system
I would like to know the best way of saving all these different objects from different controllers into my serialized file.
Currently, I have been reading the serialized file in each controller to populate the array lists. this is my reading method in the "Book" controller.
And I have a save to file method as well however I'm not sure how to implement the ArrayList from different controllers.
private void populateArrayLists() {
System.out.print("Im here in ArrayList");
ArrayList<Object> deserialised = new ArrayList<Object>();
try {
FileInputStream file = new FileInputStream("info.ser");
ObjectInputStream inputFile = new ObjectInputStream(file);
deserialised = (ArrayList<Object>) inputFile.readObject();
inputFile.close();
file.close();
} catch (IOException | ClassNotFoundException e) {
JOptionPane.showMessageDialog(null, e.getMessage());
}
books = (ArrayList<Book>) deserialised.get(2);
}
private void saveData() {
ArrayList<Object> allData = new ArrayList<Object>();
books.add(book1);
admins.add(admin1);
users.add(user1);
allData.add(users);
allData.add(admins);
allData.add(books);
try {
FileOutputStream file;
file = new FileOutputStream("info.ser");
ObjectOutputStream outputFile = new ObjectOutputStream(file);
outputFile.writeObject(allData);
outputFile.close();
file.close();
JOptionPane.showMessageDialog(null, "Saved");
} catch (IOException e) {
JOptionPane.showMessageDialog(null, e.getMessage());
}
}
I would like a method of saving all the different objects in different controllers in one place.
Given your question description, I suggest you implement one solution where you make use of the Repository concept in the way described by Domain Driven Design. It allows you to centralize the logic for handling the collection of objects you have so far. Since you decide to use files, I recommend you to have one file per class of objects instead of one file for all your objects collections. Here you can find a basic approach, it can be improved further with generics.
I am creating a program for a small business. This program is meant to have smaller modules that, when developed, will be attatched to the rest of the program. It contains an "Article" and a "Category" class, which is contained in lists in a "ArticleDatabase" class.
This class is serialized and saved to a file to the harddrive.
The Register module is complete, and the "Receipt" class, is likewise contained within lists in a "RegisterDatabase" class, which is serialized and saved to a separate file.
System settings, are saved in the same manner.
However, now i am designing a Invoice module, and found out that i need to add a field to the "Article" class, and to the System data.
The register is now being used, and contains actual data that needs to be saved, and therefore i can't just change the class, since this gives an InvalidClassException when i load.
Since i know that this will be a common problem in the future too, i need some advice on how to tackle this problem.
How can i setup a system i which i can save a file from a class, and load the data into an updated or new version of this class, or should i approach this in an entirely new way?
I have tried loading the data form the old file in to a duplicate class with the needed fields addded, but reconfiguring the program to use the new files instead is a very cumbersome task, and if i have to do this every now and again, a lot of time will be wasted doing this.
The methods used for saving loading are as follows:
public void saveArticleDB() throws IOException {
// Write to disk with FileOutputStream
FileOutputStream f_out = new FileOutputStream("articles.data");
// Write object with ObjectOutputStream
ObjectOutputStream obj_out = new ObjectOutputStream(f_out);
obj_out.writeObject(MyMain.articleDB);
}
public ArticleDB loadArticleDB() throws IOException {
try {
FileInputStream f_in = new FileInputStream("articles.data");
ObjectInputStream obj_in = new ObjectInputStream(f_in);
Object obj = obj_in.readObject();
if (obj instanceof ArticleDB) {
return (ArticleDB) obj;
} else return null;
} catch (FileNotFoundException e) {
new MessageDialog("Article DB - File not found");
return null;
} catch (InvalidClassException e) {
new MessageDialog("Article DB - Class didnt match");
return null;
} catch (ClassNotFoundException e) {
new MessageDialog("Article DB - Class not found");
return null;
}
}
The classes that delivers data to the save file, implements Serializable, and thats the only code used regarding the saving and loading of the class.
This is my first attempt with serializing, saving and loading, which means i am quite new to this, and therefore know/understand very few of the concepts regarding these subjects.
Advice is much appreciated :-)
I'm a student in my high school's AP Computer Science course, and as a final project I have to make a stock management app.
Part of this entails a process where every time the Stock app is opened, it gets the data (stock names, symbols, and current prices) on Yahoo! Finance, and writes it to a text file called Results.txt. Later, throughout the program, this file is repeatedly referred to in order to fetch names and prices.
I have code using Scanner to read a file, shown below, so I think I should be to refer to the data later, but I don't know how to go about getting the data and writing it to a file.
What java code can I use so that every time my front end code runs, it'll start by accessing Yahoo Finance and writing the stock data to the file for me to use?
Here is my method to read data from a file, into an ArrayList of Strings, line by line
public ArrayList<String> readFile(File f){
ArrayList<String> lines = new ArrayList<String>();
try{
a = new Scanner(f);
}catch(FileNotFoundException e){
System.out.println("File not found");
}
while(a.hasNextLine())
lines.add(a.nextLine());
return lines;
}
F will be a file passed to it, either the results file or a transaction history file, and I intend for it to return an arraylist of lines to me. Does this work well?
For more easier usage, I recommend you write serializable object into file.
I guess that you use the java-yahoo-finance to implement your job.
In a Maven project:
Add following dependency,
<dependency>
<groupId>com.yahoofinance-api</groupId>
<artifactId>YahooFinanceAPI</artifactId>
<version>1.3.0</version>
</dependency>
Fetch data from web and write into file
Stock stock = YahooFinance.get("INTC");
File file = new File(RESULT_PATH);
if (!file.exists()){
file.createNewFile();
}
MyStock myStock = new MyStock();
myStock.setName(stock.getName());
myStock.setSymbols(stock.getSymbol());
myStock.setPrice(stock.getQuote().getPrice().doubleValue());
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file));
os.writeObject(myStock);
os.close();
Since Stock is not serializable, we create a MyStock class.
class MyStock implements Serializable{
private String name;
private String symbols;
private double price;
// setter and getter
}
read from file
MyStock stock = null;
try {
ObjectInputStream is = new ObjectInputStream(new FileInputStream(new File(RESULT_PATH)));
stock = (MyStock)is.readObject();
}catch (Exception e){
e.printStackTrace();
}
return stock;
Once you obtain the MyStock object here, you can directly handle it.
Actually, I searched the solution for that in web. I also found Copy an object in Java. In my object, there are a lot mapping.
Even I use Cloneable and Copy Constructor, I still need to copy for each fields?
My requirement is to know which data changed between Old Object and New Object.
My object Example Tree :
MotorProposal
- startDate : Date ---> can change
- endDate : Date ---> can change
- customer : Cutomer
- vehicleList : List<Vehicle> ---> can chnage
- carNo : String ---> can change
- loading : int ---> can change
- cubicCapacity : int ---> can chnage
- driver : Driver ---> can change
- fullName : String ---> can change
- address : Stirng ---> can change
- license : Stirng ---> can change
- expYear : int ---> can change
- model : Model
-there other fields
-there other fields
Is there another way to create new Instance with the same value without copying for each field?
My expected program
MotorProposal oldProposal = --> come from DB
MotorProposal newProposal = org.someapi.ObjectUtil.newInstance(oldProposal);
Update
Currently, I solve this case Martin Dinov suggested. As below.
ObjCopy.java
public class ObjCopy {
public static Serializable newInstance(Serializable obj) {
Serializable result = null;
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(buffer);
oos.writeObject(obj);
oos.flush();
oos.close();
ByteArrayInputStream in = new ByteArrayInputStream(buffer.toByteArray());
ObjectInputStream ois = new ObjectInputStream(in);
return (Serializable)ois.readObject();
} catch (Exception e) {
//do nothing
e.printStackTrace();
}
return result;
}
}
Test.java
public class Test {
public static void main(String[] args) {
Country country = new Country();
country.setName("Myanmar");
Province province_1 = new Province();
province_1.setCountry(country);
province_1.setName("Yangon");
Province province_2 = (Province)ObjCopy.newInstance(province_1);
province_2.getCountry().setName("USA");
System.out.println(province_1.getName() + "-" + province_1.getCountry().getName());
System.out.println(province_2.getName() + "-" + province_2.getCountry().getName());
}
}
Output
Yangon-Myanmar
Yangon-USA
How about Yoni Roit's second proposal from the Stackoverflow link you provide? In other words, serialize and then deserialize the object - so this will result in deep copying your object byte-wise. You need to have your class implement Serializable. As long as all class fields can be serialized, this approach should work. However, serializing and deserializing objects can be quite slow apparently - probably not an issue if you want to do this out of convenience, rather than out of efficiency. Here's a simple example of re-creating a new ArrayList:
ArrayList<Integer> foo = new ArrayList<Integer>();
foo.add(5);
foo.add(3);
foo.add(1);
ArrayList<Integer> obj = null;
// Write the object out to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(foo);
out.flush();
out.close();
// Make an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(
bos.toByteArray()));
obj = (ArrayList<Integer>)in.readObject();
In your case, you'd want to type-cast to your specific class of course. This way you don't have to explicitly copy each field in the class.
No CyCDemo, there are a lot of issues about the Cloneable interface and the reason of and the reasons why Java has not implemented a deep copy.
In any case get an eye there:
https://code.google.com/p/cloning/