Java reading a vector from a txt file gives error - java

i am trying to write and read a vector to a text file. I made a class WriteVectorToFile (shown below) which makes a vector containing objects of a class called Car. The class Car implements Serializable and only contains information with setter and getter methods. In the WriteVectorToFile class i have made a createVector() method and writetoFile() method and they work. The problem in the readtoFile() method and it gives out an error (listed below). I want to know what am i doing wrong and what is causing the problem.
The error :
java.lang.NullPointerException
at WriteVectorToFile.readtoFile(WriteVectorToFile.java:73)
at WriteVectorToFile.main(WriteVectorToFile.java:110)
at __SHELL1.run(__SHELL1.java:6)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at bluej.runtime.ExecServer$3.run(ExecServer.java:725)
Code:
import java.io.*;
import java.util.Vector;
public class WriteVectorToFile{
private Car car1;
private Vector garage;
private File myFile;
private FileOutputStream out;
private FileInputStream in;
private ObjectInputStream objin;
private ObjectOutputStream objout;
public WriteVectorToFile(){
this.myFile = new File("E:/JAVA/My Java Programs/MyVectorFile.txt");
try{
myFile.createNewFile();
System.out.println("New File --> Success.");
}catch(IOException e){
e.printStackTrace();
System.out.println("New File --> Fail.");
}
}
private void writetoFile(){
try{
out = new FileOutputStream(myFile);
objout = new ObjectOutputStream(out);
}catch(FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
try{
objout.writeObject(garage);
objout.close();
System.out.println("Write File --> Success.");
}catch(IOException e){
System.out.println("Write File --> Fail.");
e.printStackTrace();
}
}
private void readtoFile(){
try{
FileInputStream in = new FileInputStream(myFile);
ObjectInputStream objin = new ObjectInputStream(in);
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
// Object obj = null;
Vector tempVec = new Vector();
try{
ERROR Line 73 : tempVec = (Vector) objin.readObject();
objin.close();
System.out.println("Read File --> Success.");
}catch(Exception e){
System.out.println("Read File --> Fail.");
e.printStackTrace();
}
//Car tempg = new Car();
//tempg = (Car) vecNew.firstElement();
//System.out.println(tempg.toString());
//System.out.println(((Car)(vecNew.firstElement())).toString());
}
private void createVector(){
this.garage = new Vector();
// To create a vector with a specific datatype add <type>
// Vector garage = new Vector<Car>();
car1 = new Car("3245","Toyota","Ferry23",(double)34500);
this.garage.add(car1);
this.garage.add(new Car("3232","Fiat","MozoZ3",(double)25000));
this.garage.add(new Car("2345","Mazda","ZenFix",(double)13700));
}
public static void main (String[] args){
WriteVectorToFile test = new WriteVectorToFile();
test.createVector();
test.writetoFile();
test.readtoFile();
}
}

Firstly, apologies as I cannot post it as comment so putting it into an answer block:
Your problem is the scope mismatch involving try-catch blocks . If you have done any C++, the objects are passed by value or reference so this could have been avoided very conveniently. But Java passes everything by value so when you do:
try{
FileInputStream in = new FileInputStream(myFile);
ObjectInputStream objin = new ObjectInputStream(in);
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
The object objin is created inside try-catch scope which is NOT the same when you use it in:
tempVec = (Vector) objin.readObject();
objin.close();
System.out.println("Read File --> Success.");
}catch(Exception e){
System.out.println("Read File --> Fail.");
e.printStackTrace();
}
So the solution is put everything in one "try" block and catch all the exceptions seperately (or even together using Exception as superclass [not a good practice]). This should do the job. Tell us if you manage to solve it anyway.

Because you have defined the private ObjectInputStream objin; as instance variable and it is null. So when you invoke objin.readObject(); on null will throw NullPointerException. Inside the readtoFile() method, you do something like this:
try{
FileInputStream in = new FileInputStream(myFile);
ObjectInputStream objin = new ObjectInputStream(in);
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
That defines a new local ObjectInputStream objin = new ObjectInputStream(in); inside try block, which is invisible to the code tempVec = (Vector) objin.readObject(); ouside try-catch block. Here objin refers to the instance variable declared at instance level and it is null. To correct it change
ObjectInputStream objin = new ObjectInputStream(in);
to
objin = new ObjectInputStream(in);
inside the try block.

Related

Updating serialzed ArrayList in java

I am making a project where I need to save data to binary file using serilazation. I know how to read and write parameterized ArrayList using ObjectInputStream, ObjectOutputStream and FileInputStream. However I have no idea how I would go about updating ArrayList when new value is added or deleted.
import java.io.*;
import java.util.ArrayList;
public class testSerialization {
public static void main(String[] args){
String fileName = "test.bin";
ArrayList<Integer> integers = new ArrayList<>();
// Insert sample data
for (int i=0; i<10; i++){
integers.add(i);
}
try{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName));
oos.writeObject(integers);
oos.flush();
oos.close();
}catch(Exception e){
System.out.println(e);
}
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName));
ArrayList<Integer> ps = (ArrayList<Integer>) ois.readObject();
System.out.println(ps);
ois.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
One way I can do it is that I just override all the data with updated data everytime I get a change, but there is probably better alternative solution

How to avoid java.io.StreamCorruptedException?

I have a method that writes data from a list to a file, a method that reads data from a file into a list and a method that writes data from a list in a file to the specified number of times. I'm trying to extract data from a file after I use the first method writeFile () everything works fine. I read the data from the file into the list by readFile () method. After that I use my method which writes to the file the number of times I need, everything is fine, it writes multyWrite (). But after that I can not read the data from the file in the readFile () method since I get `
Exception stack trace:
Exception in thread "main" java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1599)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at ProductService.readFile(ProductService.java:47)
at Main.main(Main.java:21)
I know that I should use objectOutputStream.reset (), but where would it be better to use it?
private String fileName;
private ProductInterface<FlyingMachine> productService = new ProductInterfaceImpl();
private ObjectOutputStream objectOutputStream;
private FileOutputStream fileOutputStream;
public ProductService(String fileName) throws IOException {
this.fileName = fileName;
fileOutputStream = new FileOutputStream(fileName);
this.objectOutputStream = new ObjectOutputStream(fileOutputStream);
}
public void writeFile() throws IOException {
try {
for (FlyingMachine f : productService.getProductContainer()) {
objectOutputStream.writeObject(f);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (objectOutputStream != null) {
objectOutputStream.flush();
objectOutputStream.close();
fileOutputStream.close();
}
}
}`
public void readFile() throws IOException {
ObjectInputStream objectInputStream = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(fileName);
objectInputStream = new ObjectInputStream(fileInputStream);
while (fileInputStream.available() > 0) {
FlyingMachine flyingMachine = (FlyingMachine) objectInputStream.readObject();
productService.getProductContainer().add(flyingMachine);
}
} catch (ClassNotFoundException | EOFException e) {
e.printStackTrace();
} finally {
if (objectInputStream != null) {
objectInputStream.close();
fileInputStream.close();
}
}
}
public void multyWrite(int number) throws IOException {
for (int i = 0; i < number; i++) {
try {
fileOutputStream = new FileOutputStream(fileName, true);
objectOutputStream = new ObjectOutputStream(fileOutputStream);
for (FlyingMachine f : productService.getProductContainer()) {
objectOutputStream.writeObject(f);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (objectOutputStream != null) {
objectOutputStream.flush();
objectOutputStream.close();
}
}
}
}
You create a new ObjectOutputStream in the constructor. In writeFile you use that OOS instance and close it. But in multyWrite you don't use it and instead create new instances.
Now when you call multyWrite without having called writeFile first, that first OOS will still be open, but the OOS you create in multyWrite doesn't know that - thus causing your file to have two OOS headers after another.
And then when you try to read such a file, the ObjectInputStream will find the first header (all is fine) and then unexpectedly find the second header, while it expected a type code. That header starts with 0xAC, hence throwing the exception message "invalid type code: AC".
To fix this, either have multyWrite use the OOS constructed in your constructor, the same way writeFile does, or make sure that that OOS is closed before you create a new one.
It's generally not a good idea to open a stream (of any kind) in a constructor and then rely on external code calling a specific method to close it. Better create streams when you need them and close them directly.

Serialize multiple entries to the same file

I'm basically making a journal app where each individual journal entry needs to persist, and I would like to keep all entries in a single file.
I've seen tons of tutorials on serializing a single object and so I came up with this solution, (which doesn't work) but even if I manage to fix it, it feels like a sloppy solution.
(Here I'm trying to serialize an arraylist, and each time I save an entry, i de-serialize the list and add the new entry to the list before serializing again)
To clarify, my question is: s this a good way to save objects to the same file, on multiple occasions?
Or does anyone have some tips about something else I should try, links to videos or documentation regarding this is also appreciated.
public class Serializer
{
//Calls readFile and adds the returned entries to an ArrayList
//Add the target object to the list and write to the file
public static void writeToFile(Object target)
{
ArrayList entries = new ArrayList();
entries = readFile();
entries.add(target);
String filename = "entries.bin";
FileOutputStream fileOut = null;
ObjectOutputStream objOut = null;
try
{
fileOut = new FileOutputStream(filename);
objOut = new ObjectOutputStream(fileOut);
objOut.writeObject(entries);
objOut.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
//Reads the file and returns all entries in a list
public static ArrayList readFile ()
{
ArrayList persistedEntries = new ArrayList<>();
String filename = "entries.bin";
FileInputStream fileIn = null;
ObjectInputStream objIn= null;
try
{
fileIn = new FileInputStream(filename);
objIn = new ObjectInputStream(fileIn);
persistedEntries = (ArrayList) objIn.readObject();
objIn.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
catch(ClassNotFoundException ex)
{
ex.printStackTrace();
}
return persistedEntries;
}
}
Is this a good way to save objects to the same file, on multiple occasions?
I would argue no. This is because your method writeToFile or more accurately appendToFile can introduce strange behaviour in edge cases (such as entries.bin having an unexpected object). I would argue for this:
Use writeToFile(ArrayList<Object> target) to overwrite the file with the specified array. Then add a method appendToFile(Object target) that handles the process of reading from entries.bin from the disk, appending target then writing the array to the disk. This has the advantage of separating any logic related to 'merging' the new object target with the file on disk, and the actual logic of writing to the entries.bin file.
If just a learning exercise I would go with the above. Potential resource
Adding a reformatted version:
public class Serializer
{
private String filename;
// pass in "entries.bin"
public Serializer(String filename) {
this.filename = filename;
}
public void append(Object target) {
// readfile will return at least empty arraylist
ArrayList entries = readFile();
entries.add(target);
serialize(entries);
}
public void serialize(ArrayList entries)
{
FileOutputStream fileOut = null;
ObjectOutputStream objOut = null;
try
{
fileOut = new FileOutputStream(filename);
objOut = new ObjectOutputStream(fileOut);
objOut.writeObject(entries);
objOut.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
//Reads the file and returns all entries in a list
public ArrayList deserialize ()
{
ArrayList persistedEntries = new ArrayList<>();
FileInputStream fileIn = null;
ObjectInputStream objIn = null;
try
{
fileIn = new FileInputStream(filename);
objIn = new ObjectInputStream(fileIn);
Object result = objIn.readObject();
if (!(result instanceof ArrayList)) {
// read object is not an arraylist
}
persistedEntries = (ArrayList) objIn.readObject();
objIn.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
catch(ClassNotFoundException ex)
{
ex.printStackTrace();
}
return persistedEntries;
}
}

Strange issue when creating a new file

I have the below 2 methods, supposed to read and write to a file:
/* Write content to a file */
private void writeToFile(ArrayList<String> list) {
#SuppressWarnings("unused")
File file = new File("jokesBody1.bjk");
FileOutputStream fos;
if(list != null){
try {
fos = openFileOutput("jokesBody1.bjk",Context.MODE_PRIVATE);
ObjectOutputStream out = new ObjectOutputStream(fos);
out.writeObject(list);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}else{
try {
fos = openFileOutput("jokesBody1.bjk",Context.MODE_PRIVATE);
ObjectOutputStream out = new ObjectOutputStream(fos);
out.writeObject("");
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/* Read file's content */
private ArrayList<String> readFromFile() {
File file = new File("jokesBody1.bjk");
ArrayList<String> list = new ArrayList<String>();
try {
ObjectInputStream ois = new ObjectInputStream( new FileInputStream( file ) );
try {
list = (ArrayList)ois.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ois.close();
} catch (IOException e) {
Log.e("log activity", "Can not read file: " + e.toString());
}
return list;
}
When I'm calling the above methods I'm getting this error:
02-15 10:28:48.165: E/log activity(1743): Can not read file: java.io.FileNotFoundException: /jokesBody1.bjk: open failed: ENOENT (No such file or directory)
Ok, it clearly says that the file is not there, but, isn't this code supposed to create it:
File file = new File("jokesBody1.bjk");
Why I'm getting this error? I know that I'm missing something small - probably a piece of code that creates the file(I'm not sure), but as a beginner, I'm not able to spot the issue.
File file = new File("jokesBody1.bjk");
Just creates a File objects that points to that path, but no actual file.
Use
file.createNewFile();
To actually create the file.
Ok, it clearly says that the file is not there, but, isn't this code supposed to create it:
Actually, no. It only creates a File object, an then java assumes that file to exist.

Code highlighted as syntax error. Why?

I'm new to java and I'm trying to write this code but somehow it sees it as an error when using my variables. which has been declared ofc.
import java.io.*;
public class FileRead {
public void readCountries(String file){
try{
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("countries"));
Object obj = null;
while ((obj = inputStream.readObject()) != null) {
if (obj instanceof Country) {
System.out.println(((Country)obj).toString());
}
}
} catch (EOFException ex) { //This exception will be caught when EOF is reached
System.out.println("End of file reached.");
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
//Close the ObjectInputStream
try {
if (inputStream != null) { //////////ERROR: inputStream cannot be resolved to a variable
inputStream.close(); //////////// Same here
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
Move your inputStream declaration outside try block. If you define inside try, it is not visible outside the try block.
ObjectInputStream inputStream = null;
try{
inputStream = new ObjectInputStream(new FileInputStream("countries"));
........
}
It's pretty simple, you are trying to access a variable outside of the scope where it was declared. Here is a simplified example of your problem:
try {
int i = 0;
} catch(Exception e) {
//...
}
++i;
You see? Once the variable escapes the braces where it was declared, it's lost. In your example:
try{
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("countries"));
//...
} finally {
if (inputStream != null) { //////////ERROR: inputStream cannot be resolved to a variable
inputStream.close(); //////////// Same here
}
}
just drag inputStream outside:
ObjectInputStream inputStream = null;
try{
inputStream = new ObjectInputStream(new FileInputStream("countries"));
//...
} finally {
if (inputStream != null) {
inputStream.close();
}
}
Or even better use try-with-resources (hey, Java 7 is no longer new and fresh!)
try(ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("countries")) {
//...
}
No finally, close(), etc. needed.
You define inputStream inside the scope of the try block, and hence cannot access it outside.
You can resolve this by doing something like,
ObjectInputStream inputStream = null;
try{
inputStream = new ObjectInputStream(new FileInputStream("countries"));
...
}
i.e. defining the variable outside of the try-block and assigning it within. This way, you can access inputStream outside of the try-block.
It's a problem of variable scope.
Your inputStream variable belongs to try block that doesn't encompass the same scope as the catch or finally block causing inputStream to be undeclared in the catch or finally block. Thus, this variable is unknown within the catch block, explaining your "variable may not be initialized" shown by your IDE.
Simply, initializes your variable to null outside the first try/catch as follows:
ObjectInputStream inputStream = null;
try{
The variable is declared inside the try { ... } block, so its scope and visibility is restricted to it. You can't use it outside.
You can declare it outside the block:
ObjectInputStream inputStream = null;
try{
inputStream = new ObjectInputStream(new FileInputStream("countries"));
//...
} catch (EOFException ex) { //This exception will be caught when EOF is reached
//...
} finally {
//Close the ObjectInputStream
try {
if (inputStream != null) { //////////ERROR: inputStream cannot be resolved to a variable
inputStream.close(); //////////// Same here
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
inputstream does not exist outside the {} of your try/catch

Categories