So I'm making a notepad application that logs date entered, a subject, and a body text field. When I hit my post button, everything appears properly in my ListView, but when I close the application and re-open it, only the date remains intact and the other two values are NULL. Below is the code I'm using.
public class LogList implements Serializable {
private String logDate;
private String logBody;
private String logSubject;
public LogList(String date, String LogBody, String LogSubject){
super();
this.logDate = date;
this.logBody = logBody;
this.logSubject = logSubject;
}
Back in my main class, I have my method that is supposed to save the three values into an ArrayList lts.
private void saveInFile(String subject_text, String date, String body_text ){
LogList lt = new LogList(date, subject_text, body_text);
lts.add(lt);
saveAllLogs();
}
Now if I change the order of the values in my new LogList, only the first one will be properly displayed after I close my app and reopen it. The following are my saveAllLogs method and my loadFromFile method.
private ArrayList<String> loadFromFile(){
ArrayList<String> logs = new ArrayList<String>();
try {
FileInputStream fis = openFileInput(FILENAME);
ObjectInputStream ois = new ObjectInputStream(fis);
while (true) {
LogList lt = (LogList) ois.readObject();
logs.add(lt.toString());
lts.add(lt);
}
}
catch (FileNotFoundException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
catch (ClassNotFoundException e) { e.printStackTrace(); }
return logs;
}
private void saveAllLogs() {
try {
FileOutputStream fos = openFileOutput(FILENAME, 0);
ObjectOutputStream oos = new ObjectOutputStream(fos);
for (LogList lti : lts) {
oos.writeObject(lti);
}
fos.close();
}
catch (FileNotFoundException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
}
Any help would be greatly appreciated!
For one thing,
public LogList(String date, String LogBody, String LogSubject){
super();
this.logDate = date;
this.logBody = logBody;
this.logSubject = logSubject;
}
Seems wrong. As you have capitalized argument names, but you're setting the members with lowercase names.
Do you mean:
public LogList(String date, String logBody, String logSubject){
super();
this.logDate = date;
this.logBody = logBody;
this.logSubject = logSubject;
}
EDIT: Trivial thing, not impacting your code: You don't need your call to super() in your constructor as you're not extending any class.
Related
I'm trying to read objects from a file then add them to an Array List of Ticket. But it's not working. May I please know where's the problem?
public void writeTicketToFile(Ticket ticket) {
try {
FileOutputStream fileOut = new FileOutputStream("tickets.txt");
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(ticket.toString());
objectOut.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void readTicketFromFile(){
ArrayList<Ticket> tickets = new ArrayList<Ticket>();
try {
FileInputStream fi = new FileInputStream(new File("tickets.txt"));
ObjectInputStream oi = new ObjectInputStream(fi);
Ticket ticket;
while (ticket=oi.readObject() != null){
tickets.add((Ticket)oi.readObject());
}
System.out.println(tickets);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
One of your main problems lies here:
while (ticket=oi.readObject() != null){
tickets.add((Ticket)oi.readObject());
}
Compare the fact that you're trying to read a Ticket object out of a file with the way you're writing the Ticket to the file:
objectOut.writeObject(ticket.toString());
As you can see, you're converting the Ticket to a String and writing the String to the file. Then when you try to read, you're trying to read a Ticket. Instead, you should read a String, and then convert the String into a Ticket in code.
If Ticket is serializable, you may instead just be able to remove .toString() from the write step, but I've never worked with object streams, so I can't say 100% if that will work.
There are a lot of issues here:
Make sure your Ticket implements Serializable interface for writing/reading objects from/to file as in this simple example:
public class Ticket implements Serializable{
private String name;
private LocalDateTime issued;
public Ticket() {
}
public Ticket(String name, LocalDateTime issued) {
this.name = name;
this.issued = issued;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #return the issued
*/
public LocalDateTime getIssued() {
return issued;
}
/**
* #param issued the issued to set
*/
public void setIssued(LocalDateTime issued) {
this.issued = issued;
}
}
Now pay attention to while writing tickets to a file to write them one at a time. You can achieve it by iterating thru your list of tickets and writing it one at a time, something like:
for (int i = 0; i < tickets.size(); i++) {
objectOut.writeObject(tickets.get(i));
}
Also, make sure to close your ObjectInputStream after reading as it will surely throw EOFException at the end, take a look at implementation of it in readTicketFromFile method.
public class SerializationAndDeserializationOfTicket {
public static void main(String[] args) {
List<Ticket> listOfTickets = new ArrayList<>();
listOfTickets.add(new Ticket("Concert 1", LocalDateTime.now()));
listOfTickets.add(new Ticket("Concert 2", LocalDateTime.now()));
listOfTickets.add(new Ticket("Concert 3", LocalDateTime.now()));
writeTicketToFile(listOfTickets);
readTicketFromFile();
}
public static void writeTicketToFile(List<Ticket> tickets) {
try {
FileOutputStream fileOut = new FileOutputStream("tickets.txt");
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
for (int i = 0; i < tickets.size(); i++) {
objectOut.writeObject(tickets.get(i));
}
objectOut.close();
} catch (IOException e) {
System.err.println("JVM reported an IO exception. Please, take a look.");
}
}
public static void readTicketFromFile() {
ArrayList<Ticket> tickets = new ArrayList<>();
try {
FileInputStream fi = new FileInputStream(new File("tickets.txt"));
ObjectInputStream oi = new ObjectInputStream(fi);
while (true) {
try {
Ticket ticket = (Ticket) oi.readObject();
tickets.add(ticket);
System.out.println(ticket.getName() + " " + ticket.getIssued());
} catch (EOFException ex) {
oi.close();
break;
}
}
} catch (IOException | ClassNotFoundException e) {
System.err.println("JVM reported an IO/ClassNotFound exception. Please, take a look.");
}
}
Just add the Ticket objects into an ArrayList and write the list (instead of each object one by one) as a single object. Then read the list from the file in your readTicketFromFile() method as :
ArrayList<Ticket> ticketsList = (ArrayList<Ticket>)oi.readObject();
I am performing a project, where so far in the discipline, we can not use database to persist the data. I am persisting the data in .tmp files. The first time I persisted the list of doctors, and it worked, but now that I'm trying to persist the patient user data, but this error happens, that file is not found.
These are my load, anda save methods in the class "SharedResources":
public void loadUserPatient(Context context) {
FileInputStream fis1;
try {
fis1 = context.openFileInput("patient.tmp");
ObjectInputStream ois = new
ObjectInputStream(fis1);
userPatient = (UserPatient) ois.readObject();
ois.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
} catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
public void saveUserPatient(Context context) {
FileOutputStream fos1;
try {
fos1 = context.openFileOutput("patient.tmp",
Context.MODE_PRIVATE);
ObjectOutputStream oos =
new ObjectOutputStream(fos1);
oos.writeObject(userPatient);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
here is the whole class: https://ideone.com/f3c74u
the error is happening on line 16 of MainActivity:
SharedResources.getInstance().loadUserPatient(this);
here is the whole class "Main": https://ideone.com/OyiljP
And I think this error is ocurring because of the 52nd line of the UserPatientAdd class:
SharedResources.getInstance().getUserPatient();
because when I work with an ArrayList, I put an add at the end of the line, like:SharedResources.getInstance().getDoctors().add(doctor);
And I get confused on how to proceed when I deal only with a user.
This is the whole UserPatientAdd class: https://ideone.com/clUSa3
How can I solve this problem?
You need to set the UserPatient using something like this
In your SharedResources class, create a new method:
public void setUserPatient(UserPatient user) {
userPatient = user;
}
Then in your UserPatientAdd class set the new object:
UserPatient userPatient = new UserPatient (birth, name, bloodType, bloodPressure, cbpm, vacinesTaken, vacinesToBeTaken,
allergies,weight, height, surgeries, desease);
SharedResources.getInstance().setUserPatient(userPatient);
Done
I've working on an assignment that asks me to alter a method in a class to take content from a textfile and use it to create multiple instances of various subclasses of the Event Class. Here is the text file:
Event=ThermostatNight,time=0
Event=LightOn,time=2000
Event=WaterOff,time=8000
Event=ThermostatDay,time=10000
Event=Bell,time=9000
Event=WaterOn,time=6000
Event=LightOff,time=4000
Event=Terminate,time=12000
The Event=* is the name of the subclass, while time=* is a parameter that is used in the subclass' constructor. The Event class itself is an abstract class and is used for inheritance.
public class Restart extends Event {
Class eventClass;
String eventInput;
Long timeDelay;
public Restart(long delayTime, String filename) {
super(delayTime);
eventsFile = filename;
}
public void action() {
List<String> examples = Arrays.asList("examples1.txt", "examples2.txt", "examples3.txt", "examples4.txt");
for (String example : examples) {
//finding pattern using Regex
Pattern pattern = Pattern.compile(example);
Matcher matcher1 = pattern.matcher(eventsFile);
if (matcher1.find()) {
File file = new File(example);
String line;
try {
FileReader fileReader = new FileReader(file);
Scanner sc = new Scanner(file);
BufferedReader bufferedReader =
new BufferedReader(fileReader);
while ((line = bufferedReader.readLine()) != null) {
sc.useDelimiter("\n");
//Parsing through text
while (sc.hasNext()) {
String s = sc.next();
String[] array1 = s.split(",");
String[] array2 = array1[0].split("=");
eventInput = array2[1];
String[] array3 = array1[1].split("=");
String timeInput = array3[1];
try {
eventClass = Class.forName(eventInput);
timeDelay = Long.parseLong(timeInput);
try {
addEvent(new eventClass(timeDelay));
}
//catch block
catch(NoSuchMethodException e){
System.out.println("No Such Method Error");
} catch (Exception e) {
System.out.println("error");
}
//catch block
} catch (ClassNotFoundException ex) {
System.out.println("Unable to locate Class");
} catch (IllegalAccessException ex) {
System.out.println("Illegal Acces Exception");
} catch (InstantiationException ex) {
System.out.println("Instantiation Exception");
}
}
}
//Close bufferedReader
bufferedReader.close();
}
//catch block
catch (FileNotFoundException ex) {
System.out.println(
"Unable to open file '" +
file + "'");
} catch (IOException ex) {
ex.printStackTrace();
}
break;
}
//if input match is not found
else {
System.out.println("No Match Found");}
}
}
I seem to be able to parse fine, and find the strings i'm looking for, but I'm not able to use eventInput which I've pulled from the text file as a parameter to create a new event.
eventClass = Class.forName(eventInput);
doesn't seem to be turning my string into an acceptable parameter either.
Any help would be much appreciated!
I know I'm probably missing something key here, but I've been staring at it too long that it seems like a lost cause.
Here is the Event class:
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime = delayTime;
start();
}
public void start() { // Allows restarting
eventTime = System.currentTimeMillis() + delayTime;
}
public boolean ready() {
return System.currentTimeMillis() >= eventTime;
}
public abstract void action();
} ///:~
I think you've misunderstood how reflection works. Once you have a Class object (the output from Class.forName(), you have to find the appropriate constructor with
Constructor<T> constructor = eventClass.getConstructor(parameter types)
and then create a new instance with
constructor.newInstance(parameters);
For a no-arg constructor there's a shortcut
eventClass.newInstance();
I strongly suggest you read the tutorials on reflection before proceeding.
I am not sure why file , BankAccount.ser is empty after successful run of below code. BankAccount.ser file is a class path resource. After successful run of SuccessfulSerializationTestDriver , BankAccount.ser is zero bytes on disk and has no contents.
public class SuccessfulSerializationTestDriver {
public static void main(String[] args) {
long accountNumber=12033456;
String bankName="SBI";
String branch="NOIDA";
SerializableBankAccount sBankAccount = new SerializableBankAccount();
sBankAccount.setAccountNumber(accountNumber);
sBankAccount.setBankName(bankName);
sBankAccount.setBranch(branch);
try(FileOutputStream fileOut =new FileOutputStream("BankAccount.ser")){
ObjectOutputStream out= new ObjectOutputStream(fileOut);
out.writeObject(sBankAccount);
out.flush();
out.close();
System.out.println("Bank Account is successfully serialized");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Serializable class is ,
public class SerializableBankAccount implements Serializable {
private static final long serialVersionUID = 1L;
private long accountNumber;
private String bankName;
private String branch;
public long getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(long accountNumber) {
this.accountNumber = accountNumber;
}
public String getBankName() {
return bankName;
}
public void setBankName(String bankName) {
this.bankName = bankName;
}
public String getBranch() {
return branch;
}
public void setBranch(String branch) {
this.branch = branch;
}
#Override
public String toString(){
return accountNumber+","+bankName+","+branch;
}
}
EDIT : I wrote deserializer and I am getting object successfully - so it just seems a visibility issue. Somehow file is shown of zero bytes.
public class SuccessfulDeSerializationTestDriver {
public static void main(String[] args) {
SerializableBankAccount sBankAccount = null;
try(FileInputStream fileIn =new FileInputStream("BankAccount.ser")){
ObjectInputStream inStream= new ObjectInputStream(fileIn);
sBankAccount= (SerializableBankAccount) inStream.readObject();
inStream.close();
System.out.println("Successfully Deserialized Object is "+sBankAccount);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Successfully Deserialized Object is 12033456,SBI,NOIDA
If the file you're looking at is zero bytes, but it deserializes successfully, it sounds like the file is being created elsewhere. Perhaps specify the path explicitly when you create the file name for a start. The file with size 0, may be from an older run - delete that on disk, and see if it gets created again.
I am not able to recreate the problem you're having. When I run your code the BankAccount.ser file is created and is not empty. In fact I wrote a deserialization test to see if I could get the object back by reading the file and it works fine.
Here is the deserializing class in case you want it:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeserializationTestDriver {
public static void main(String[] args) {
try(FileInputStream fileInput =new FileInputStream("BankAccount.ser")){
ObjectInputStream input = new ObjectInputStream(fileInput);
SerializableBankAccount sBankAccount = (SerializableBankAccount) input.readObject();
input.close();
System.out.println("Bank Account is successfully deserialized: "+sBankAccount.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
I also added a toString method to your SerializableBankAccount:
#Override
public String toString() {
return "SerializableBankAccount [accountNumber=" + accountNumber
+ ", bankName=" + bankName + ", branch=" + branch + "]";
}
After running your serialization code and then running the above deserialization I get this output:
Bank Account is successfully deserialized: SerializableBankAccount [accountNumber=12033456, bankName=SBI, branch=NOIDA]
So clearly the code is fine, which means it has to be something to do with the environment. I suggest checking whether you're running the program with correct privileges, permissions, etc. It seems that something external to your code is preventing you from writing to the file. Either that or perhaps you're looking at the wrong file, verify you have the correct path and check the file creation and modification dates.
may i know why? i have passed in three strings to the addTab method and it is there in the variable when i debug but it says it is null why is that so? i have also instantiated the arrayList
public class STFile implements Serializable{
private ArrayList<String> qnsTitle;
private ArrayList<String> qnsImagePath;
private ArrayList<String> qnsSoundPath;
private Boolean fileExist;
//Constructor for STFile,gets existing data files if exists and load values from it to data files arraylists, if dont exist
//arraylists for data file will be instantiated.
public STFile()
{
setFileExists(checkIfAllFileExist());
if(getFileExist())
{
try {
setQnsTitle(STFile.readFile(STMain.TITLES_PATH));
setQnsImagePath(STFile.readFile(STMain.IMAGES_PATH));
setQnsSoundPath(STFile.readFile(STMain.SOUNDS_PATH));
}catch(IOException e)
{
System.out.println("in class STFile, IOEXception");
}catch(ClassNotFoundException e)
{
System.out.println("in class STFile, ClassNotFoundException");
}
}else
{
File titleFile = new File(STMain.TITLES_PATH);
File imageFile = new File(STMain.IMAGES_PATH);
File soundFile = new File(STMain.SOUNDS_PATH);
qnsTitle = new ArrayList<String>();
qnsImagePath = new ArrayList<String>();
qnsSoundPath= new ArrayList<String>();
}
}
public void addTab(String title,String imagePath,String soundPath)
{
getQnsTitle().add(title);
getQnsImagePath().add(imagePath);
getQnsSoundPath().add(soundPath);
try {
writeFiles();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("in STFile addtab Exception");
e.printStackTrace();
}
}
public static ArrayList<String> readFile(String filePath) throws ClassNotFoundException, IOException
{
ArrayList<String> arraylist = new ArrayList<String>();
ObjectInputStream obj_in = null;
FileInputStream f_in = null;
try {
f_in = new FileInputStream(filePath);
obj_in = new ObjectInputStream (f_in);
arraylist = (ArrayList<String>)obj_in.readObject();
return arraylist;
}catch(Exception e){
return null;
}finally{
f_in.close();
obj_in.close();
return null;
}
}
main method.
STFile file = new STFile();
file.addTab("Title", "image", "sound");
it keeps throwing
Exception in thread "main" java.lang.NullPointerException
at STFile.addTab(STFile.java:53)
at STMain.main(STMain.java:18)
Your readFile method will always return null, because you've got return null; in your finally block.
So if the file exists, qnsTitle (etc) will be null, causing the NullPointerException later.
I would strongly advise you not to catch Exception in the way you're doing in readFile, either. Only catch specific exceptions if you must do so at all - but in this case I wouldn't in the first place, or possibly only to wrap it in a different exception. Simply returning null from the catch block is hiding the fact that something's gone wrong, and introducing another problem further down the line. I suggest you just expand the throws clause of your method (e.g. to include IOException) and remove the catch block.
having return null; in your finally block in readFile could be the problem, try removing that.