So I am pretty much new at this but I have built a library project that has an ArrayList BookList which in return has elements such as String Title, String Author, and int Quantity. I have an add method and a display method and I want to create a method that I am able to save and load the BookList when I I give the appropriate input to do so. Moreover I want to do so, so when I load the BookList I can make changes to the elements in the ArrayList and it's not just reading from the file.
public class Library implements Serializable{...}
Inside this class are my methods of saving and loading which are called in the main as well as the constructors for the ArrayList.
Save
public void save(){
try{
FileOutputStream fileOut = new FileOutputStream("BookList.tmp");
ObjectOutputStream objOut = new ObjectOutputStream(fileOut);
objOut.writeObject(BookList);
objOut.close();
}catch(Exception ev){}
}//end of save()
Load
public void load(){
try{
FileInputStream fileInput = new FileInputStream("BookList.tmp");
ObjectInputStream objInput = new ObjectInputStream(fileInput);
List<Book> BookList = (List<Book>) objInput.readObject();
objInput.close();
}
catch (Exception ev){}
}//end of load()
Display
public void displayBooks(){
String t;
String a;
int q;
String s;
Book bo = new Book();
for(int i = 0; i<BookList.size(); i++){
bo = BookList.get(i);
t = bo.gettitle();
a = bo.getauthor();
q = bo.getquantity();
System.out.println(i + "." + t + " " + a + " " + q);
}//end of loop
}//end of displayBooks()
But so far through the display method I have I am not able to see the BookList so I don't know if the save method works in the first place as well. So I want to know if the problem lies here or somewhere else.
The problem is in your load(), you read the book list from the ObjectInputStream, but you simply assigned to a local variable. I believe (though poorly named) your BookList is an instance variable.
So your load() should look like
public void load(){
try{
ObjectInputStream objInput = new ObjectInputStream(FileInputStream("BookList.tmp"));
this.books = (List<Book>) objInput.readObject();
objInput.close();
}
catch (Exception ignored){
// please add some handling please!
}
}
Most probable cause of your problem is that BookList in display() method and the one in load() method are different.
In display method, you are referring to BookList that is an instance variable but in load method, you have stored the result of objInput.readObject() method in a local variable with the same name BookList. I think you wanted to store the result in BookList that is an instance variable.
Try changing
List<Book> BookList = (List<Book>) objInput.readObject();
to
BookList = (List<Book>) objInput.readObject();
Related
How to write a constructor that holds the sorted array, Then write it to a file with a method like getDatabase that returns an object that has been passed the sorted array.
Database class:
public Person[] entry; // this needs to be an array that will hold the person obj each new entry to the array is added to the next avail pos in list
public Database(int capacity) {
entry = new Person[capacity];
size = 0;
}
public Person[] getDatabase() {
return entry;
}
Storage Class:
public dataBase writeCommaSeparated(Database data) throws IOException {
Database db = new Database();
PrintStream writer = new PrintStream(file);
if(file.exists()) {
for(int i = 0; i < data.size; i++) {
writer.println(data.get(i).toFile());
}
}
writer.close();
return db;
}
public dataBase read() throws IOException {
Database db = new Database();
Scanner scan = new Scanner(file);
Person person;
//check if file has data print selected data
while(scan.hasNextLine()) {
person = parsePerson(scan.nextLine());
db.add(person);
}
scan.close();
return db;
}
These are just snippets of the code that I have. I am trying to write a sorted array into a file, and I know that it is sorting the file by age correctly but I am not sure how to write it out to a file.
in main I have:
String fileLocation = File.separator + "Users"
+ File.separator + "USERNAME"
+ File.separator + "Desktop"
+ File.separator + "DataFile.txt";
FileStorage fileStore = new FileStorage(fileLocation);
FileData data = fileStore.read(); // this invokes a method called read that reads the file
data.sort(); // sorts the file by age and prints out to the console the sorted age
fileSort.writeCommaSeparated(data); // writes to the file in a commaseparated way
Focusing on just the sorting of a csv file based on age and given your description, this was about the simplest solution that came to mind.
public class PersonDatabase {
private ArrayList<String[]> people = new ArrayList();
// Reads the given input file and loads it into an ArrayList of string arrays.
public PersonDatabase(String inputFile) throws IOException {
BufferedReader in = new BufferedReader(new FileReader(inputFile));
for (String line = null; null != (line=in.readLine()); ) {
people.add(line.split(",")); // convert csv string to an array of strings.
}
in.close();
}
private static final int AGE_COLUMN_INDEX=2; // Identifies the 'age' column
// performs a numeric comparison on the 'age' column values.
int compareAge(String[] a1, String[]a2) {
return Integer.compare(
Integer.parseInt(a1[AGE_COLUMN_INDEX]),
Integer.parseInt(a2[AGE_COLUMN_INDEX]));
}
// Sorts the list of people by age and writes to the given output file.
public void writeSorted(String outputFile) throws IOException {
PrintWriter out = new PrintWriter(new FileWriter(outputFile));
people.stream()
.sorted(this::compareAge) // sort by age
.forEach(a->{
Arrays.stream(a).forEach(s->out.print(s+",")); // print as csv
out.println();
});
out.close();
}
public static void main(String[] args) throws IOException {
PersonDatabase pdb = new PersonDatabase("persondb.in");
pdb.writeSorted("persondb.out");
}
}
Given the following input:
fred,flintstone,43,
barney,rubble,42,
wilma,flintstone,39,
betty,rubble,39,
This program produces the following output:
wilma,flintstone,39,
betty,rubble,39,
barney,rubble,42,
fred,flintstone,43,
It seemed like marshalling these arrays into Person objects just for the sake of sorting was overkill. However, if you wanted to do that, it would be pretty easy to turn an array of field values into a Person object. I'll leave that to you.
I'm trying to figure out how to delete a specific line in my Arraylist when a user types in a book ID number. However it seems that it can't find that ID number anywhere in my Arraylist.
private void removeBook()
// Removes a certain book from the Book List.
{
Scanner IDS = setbookID();
int idNum = IDS.nextInt();
if(bookList.contains(idNum)){ //problem
bookList.remove("B"+Integer.valueOf(idNum));
}
}
private Scanner setbookID(){
Scanner bookID = new Scanner(System.in);
System.out.println("Enter your book's ID number. ");
return bookID;}
bookList is an ArrayList that read through a text file and come out as a String. A line in my text file looks like this:
B998 ; Aithiopika ; Heliodorus ; 1829
However if the user types in "998" it doesn't remove this line from the ArrayList. Any ideas on how I can go about doing this? Would an iterator somewhat help?
EDIT: This is how I added the books to the ArrayList in the first place.
private ArrayList<Book> readBooks(String filename) {
ArrayList<Book> lines = new ArrayList<>();
readTextFileB(filename, lines);
return lines;
}
private void readTextFileB(String filename, ArrayList<Book> lines)
// Reads the books.txt file.
{
Scanner s = null;
File infile = new File(filename);
try{
FileInputStream fis = new FileInputStream(infile);
s = new Scanner(fis);
} catch (FileNotFoundException e){
e.printStackTrace();
}
while(s.hasNextLine())
lines.add(new Book(s.nextLine()));
}
You have multiple problems with your code. Not clear what you are trying to achieve whether you want to remove the Book object from the list. If so then you need to compare the ID field(using iterator) of the book object assuming your Book class is like below:
class Book {
int id;
Book(int id) {
this.id = id;
}
}
If above case is not the scenario then your list is a list of Book object then how can you pass String as parameter on the remove method bookList.remove("B"+Integer.valueOf(idNum));
you should pass Book object here or index number.
I have an ArrayList of Objects and i want to store them into the file and also i want to read them from the file to ArrayList. I can successfully write them into the file using writeObject method but when reading from the file to ArrayList, i can only read first object. Here is my code for reading from serialized file
public void loadFromFile() throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
myStudentList = (ArrayList<Student>) ois.readObject();
}
EDIT:
This is the code for writing list into the file.
public void saveToFile(ArrayList<Student> list) throws IOException {
ObjectOutputStream out = null;
if (!file.exists ()) out = new ObjectOutputStream (new FileOutputStream (file));
else out = new AppendableObjectOutputStream (new FileOutputStream (file, true));
out.writeObject(list);
}
Rest of my class is
public class Student implements Serializable {
String name;
String surname;
int ID;
public ArrayList<Student> myStudentList = new ArrayList<Student>();
File file = new File("src/files/students.txt");
public Student(String namex, String surnamex, int IDx) {
this.name = namex;
this.surname = surnamex;
this.ID = IDx;
}
public Student(){}
//Getters and Setters
public void add() {
Scanner input = new Scanner(System.in);
System.out.println("name");
String name = input.nextLine();
System.out.println("surname");
String surname = input.nextLine();
System.out.println("ID");
int ID = input.nextInt();
Ogrenci studenttemp = new Ogrenci(name, surname, ID);
myOgrenciList.add(studenttemp);
try {
saveToFile(myOgrenciList, true);
}
catch (IOException e){
e.printStackTrace();
}
}
Ok so you are storing whole list of students every time when new student comes in, so basicly what your file is keeping is:
List with one student
List with two students including the first one
List of 3 studens
and so on and so on.
I know you are probably thought it will write only new students in incremental fashion, but you were wrong here
.
You should rather add all students you want to store, into the list first. And then store complete list into the file , just like you are doing it.
Now, when you will be reading from the filre, first readObject will return you the list no.1 - that is why you are getting list with only one student. Second read would give you list no.2 and so on.
So you save your data you either have to:
Create complete list containig N students and store it once ito the file
Do not use list, but store students directly to the file
To read it back:
readObject once, so you will get List<Students>
Read students one by one from the file by multiple calls to readObject
This is Because I think ObjectOutputStream will return the first object from a file.
If you want all of the objects you can use for loop and use like this -:
FileInputStream fis = new FileInputStream("OutObject.txt");
for(int i=0;i<3;i++) {
ObjectInputStream ois = new ObjectInputStream(fis);
Employee emp2 = (Employee) ois.readObject();
System.out.println("Name: " + emp2.getName());
System.out.println("D.O.B.: " + emp2.getSirName());
System.out.println("Department: " + emp2.getId());
}
I'm starting with java, and now I'm doing some exercises on read/writing files.
I write strings with this format:
String wordList: word1 word2 word3; word4 word5 word6; code
Then I write this to the file using this code:
public void writeSelling(String wordList) throws IOException {
fileOutPutStream = new FileOutputStream (file);
write= new ObjectOutputStream (fileOutPutStream);
write.writeObject(wordList);
write.close();
contador++;
}
But where I'm not getting able to do it right is when reading it. For now, what I get is a null when reading the content of the file, so I think that I'm doing something wrong on the method.
This is the method I use to read the file:
public ArrayList<Object> readSelling() throws Exception, FileNotFoundException, IOException {
ArrayList<Object> objectList = new ArrayList<Object>();
fileInPutStream = new FileInputStream (file);
read= new ObjectInputStream (fileInPutStream);
for (int i=0; i<contador; i++){
objectList.add(read.readObject());
}
read.close();
return objectList;
}
I call this method this way on the main file:
public static void listSelling(){
ArrayList objects;
try{
objects = sellingObject.readSelling();
for (Iterator it = sellingObject.iterator(); it.hasNext();) {
String s = (String)it.next();
System.out.println(s.toString());
}
}catch(FileNotFoundException fnfe){
System.out.println(fnfe.getMessage());
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}catch(Exception e){
System.out.println(e.getMessage());
}
}
I don't have knowledge enough to work with the Iterator, so maybe I'm not using it right.
UPDATE -- Definition of "file.dat
This file is defined this way in other class:
private final String file;
public WriteReadObject(String file){
this.file= file;
}
Then in the main file is called this way:
static WriteReadObject selling= new WriteReadObject("file.dat");
UPDATE 2 --
I see that when I'm writing to the file, I'm writing a null value, and here is where it fails.
I have this:
String one = word1 word2 word3
String two = word4 word5 word6
Before call the write method to write on the file, I add these 2 strings in another string to get only one string. To do this I've created this method:
public String add(String c, String m){
sellinglist[contador] = c + m;
contador++;
String list= sellinglist[contador];
return list;
}
Where c is string one and m y string two
alexey28 said the right thing - you're rewriting the file and finally there's only the last insertion. Anyway it's not that simple to just change FileOutputStream argument to make it work - you can't just append to an ObjectOuputStream - if you would like to, see here. It will corrupt the stream what will result in StreamCorruptedException.
The best solution would be to open ObjectOutputStream once at the begining, write all objects you want and then close stream.
Update
It all depends on how you receive data which are to be written (If you are writing strings then it would be probably more comfortable to do it not in binary mode but text - here is tutorial which explains how to do that).
If you want code how to simply write list of Strings then you can try this:
/* writing */
public void writeSelling(List<String> wordLists) throws IOException {
fileOutPutStream = new FileOutputStream (file);
write= new ObjectOutputStream (fileOutPutStream);
for (String s : wordLists) {
write.writeObject(s);
}
write.close();
contador++;
}
Now you can change code in the place where you call writeSelling().
/* calling method */
List<String> wordLists = new ArrayList<String>();
{ // it's probably loop
String wordList = // somehow receive list like word1 word2 word3; word4 word5 word6; code
wordLists.add(wordList);
}
writeSelling(wordLists);
The rest remains the same. Don't call writeSelling() method multiple times, just once.
The problem is you are writing single object and try to read an array of objects. Every time you are writing object you rewrite current file. Change openning of output stream to append data to file (but don't forget to clear it when writing first object):
fileOutPutStream = new FileOutputStream (file, contador != 0);
I guess I don't even have to mention that I am a beginner with Java, and that this is part of an assignment. It has to be pretty obvious. What I want is to count occupied rooms in an apartment booking system, but I am totally stuck. I really can't figure out how to save the value of aptA, aptB and aptM. I need them to load every time I restart the program. Right now I'm getting the following error:
Exception in thread "main" java.lang.RuntimeException: Uncompilable
source code - Erroneous sym type: ObjectInputStream at
apartments1.Person.loadObject(Person.java:348) at
apartments1.Booking.main(Booking.java:24) Java Result: 1
I have a feeling my approach to this might be way wrong though, but this is were I ended up after desperately testing several other solutions... Now it's all a big mess, and I'm about to give up.
//creating the object
public static void addRoomCounter(){
Person roomCounter = new Person();
roomCounter.addAptA();
roomCounter.addAptB();
roomCounter.addAptM();
//adding it to arraylist
ArrayList<Person> roomList = new ArrayList<Person>();
roomList.add(roomCounter);
//saving it to file
try{
FileOutputStream saveFile = new FileOutputStream("Roomcounter.txt");
ObjectOutputStream save = ObjectOutputStream(saveFile); //cannot find symbol
save.writeObject(roomCounter);
save.close();
}catch(Exception exc){
}
}
public int addAptA(){
return aptA;
}
public int addAptB(){
return aptB;
}
public int addAptM(){
return aptM;
}
//loading object
public static void loadObject(){
try{
FileInputStream saveFile = new FileInputStream("Roomcounter.txt");
ObjectInputStream restore = ObjectInputStream(saveFile); //cannot find symbol
Object roomCounter = restore.readObject();
int aptA = (int) restore.readObject();
int aptB = (int) restore.readObject();
int aptM = (int) restore.readObject();
restore.close();
}catch(IOException | ClassNotFoundException exc){
}
}
The issue is with your reading block. You are reading the object but type-casting it to int where it should be Person. i.e.
public static void loadObject(){
try{
FileInputStream saveFile = new FileInputStream("Roomcounter.txt");
ObjectInputStream restore = ObjectInputStream(saveFile); //cannot find symbol
Person roomCounter = (Person) restore.readObject();
int aptA = (int) restore.getAptA();
int aptB = (int) restore.getAptB();
int aptM = (int) restore.getAptC()();
restore.close();
}catch(IOException | ClassNotFoundException exc){
exc.printStackTrace();
}
}
In your example, you were reading the object thrice from the serialized object on file. Rather you need to read it once and then work around.