Appendable Binary File - java

I'm working on appending objects to a binary file. My file is:
File f=new File("person.dat");
I'm getting an error (java.io.StreamCorruptedException: invalid stream header: 79737200) when I attempt to open the binary file. As far as I can tell the program writes the data just fine, but as soon as I try reading from it, I get the above error. Any help is appreciated!
My Code to write:
AppendObjectOutputStream out = null;
try {
out = new AppendObjectOutputStream(new FileOutputStream(f, true));
out.writeObject(new Student(name, age));
out.flush();
}
catch (Exception ex) {
ex.printStackTrace();
}
finally {
out.close();
}
My class for making appendable:
public class AppendObjectOutputStream extends ObjectOutputStream {
public AppendObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
#Override
protected void writeStreamHeader() throws IOException {
reset();
}
}
My partial code for reading and adding objects to an ArrayList:
Course course = new Course();
Student st = null;
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new FileInputStream("person.dat"));
try
{
while (true)
{
st = (Student) in.readObject();
course.addAccount(st); //adds student object to an ArrayList in
//class Course
}
}
catch (EOFException ex) {
}
}
catch (Exception ex) {
ex.printStackTrace();
} finally {
in.close();
}
UPDATE:
Current code to read but its not printing anything to screen:
try(ObjectInputStream ois = new ObjectInputStream(
new BufferedInputStream(Files.newInputStream(f))))
{
while (ois.available() > 0)
{
st = (Student) ois.readObject();
studentlist.addAccount(st);
System.out.println(st.getStudentNumber());
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
This is how I write to file:
Path f = Paths.get("person.dat");
try (ObjectOutputStream oos = new ObjectOutputStream(
new BufferedOutputStream(Files.newOutputStream(f, StandardOpenOption.APPEND))))
{
oos.writeObject(new Student(name,age));
}
catch(Exception ex)
{
ex.printStackTrace();
}

Rather than trying to fix your utility classes, I suggest to use the standard classes of the NIO.2 File API.
Try something like (untested):
Path personDataFilePath = Paths.get("person.dat");
// or Java 11:
// Path personDataFilePath = Path.of("person.dat");
try (ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(Files.newOutputStream(personDataFilePath, StandardOpenOption.APPEND)))){
oos.writeObject(new Student(name,age));
} catch (IOException ex) {
// do some error handling here
}
and to read the file, something like (untested):
List<Student> students = new ArrayList<>();
try (ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(Files.newInputStream(personDataFilePath)))){
while (ois.available() > 0){
students.add((Student) ois.readObject());
}
} catch (IOException ex) {
// do some error handling here
}

I have modified the code to work around making a file "appendable". I write a single arraylist object to the file (the arraylist holds a list of student objects). When I want to add a student, I read the object (arraylist) from the file, add my new student to the arraylist and write the arraylist back to the file. It is now working and my file does not have an append format.

Related

Why is this not reading in?

I know I'm not doing something correctly. I know the file needs to be Serializable to read a text file.
I've got implements Serializable on the main class. But my readText and my writeText aren't converting.
Nothing is coming in when I read and when I write out the file is not text.
public static ArrayList<String> readText() {
ArrayList<String> read = new ArrayList<String>();
Frame f = new Frame();
FileDialog foBox = new FileDialog(f, "Reading serialized file",
FileDialog.LOAD);
foBox.setVisible(true);
String foName = foBox.getFile();
String dirPath = foBox.getDirectory();
File inFile = new File(dirPath + foName);
BufferedReader in = null;
ObjectInputStream OIS = null;
try {
in = new BufferedReader(new FileReader(inFile));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
String line = null;
try {
line = in.readLine();
} catch (IOException e1) {
e1.printStackTrace();
while (line != null) {
try {
FileInputStream IS = new FileInputStream(inFile);
OIS = new ObjectInputStream(IS);
inFile = (File) OIS.readObject();
} catch (IOException io) {
io.printStackTrace();
System.out.println("An IO Exception occurred");
}
catch (ClassNotFoundException cnf) {
cnf.printStackTrace(); // great for debugging!
System.out.println("An IO Exception occurred");
} finally
{
try {
OIS.close();
} catch (Exception e) {
}
}
}
}
return read;
}
public static void writeText(ArrayList<String> file) {
ArrayList<String> write = new ArrayList<String>();
Frame f = new Frame();
FileDialog foBox = new FileDialog(f, "Saving customer file",
FileDialog.SAVE);
foBox.setVisible(true);
String foName = foBox.getFile();
String dirPath = foBox.getDirectory();
File outFile = new File(dirPath + foName);
PrintWriter out = null;
try {
out = new PrintWriter(new BufferedWriter(new FileWriter(outFile)));
for (int i = 0; i < write.size(); i++) {
String w = write.get(i);
out.println(file.toString());
}
}
catch (IOException io) {
System.out.println("An IO Exception occurred");
io.printStackTrace();
} finally {
try {
out.close();
} catch (Exception e) {
}
}
}
Nothing is coming in
You're never calling read.add(line) and you're attempting to read the file within an infinite loop inside of the catch block, which is only entered if you are not able to read the file.
Just use one try block, meaning try to open and read the file at once, otherwise, there's no reason to continue trying to read the file if it's not able to be opened
List<String> read = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(inFile)) {
String line = null;
while ((line = in.readLine()) != null) {
read.add(line); // need this
}
} catch (Exception e) {
e.printStackTrace();
}
return read;
Now, whatever you're doing with this serialized object stuff, that's completely separate, and it isn't the file or your main class that needs set to Serializable, it's whatever object you would have used a writeObject method on. However, you're reading and writing String objects, which are already Serializable.
when I write out the file is not text
Not sure what you mean by not text, but if you followed the above code, you'll get exactly what was in the initial file... Anyway, you do not need a write list variable.
You must use the individual lines of ArrayList<String> file parameter instead, but not file.toString()
for (String line:file) {
out.println(line);
}
out.close(); // always close your files and writers

How to determine if a file is empty without getting EOFException

I'm trying to create a file called manager.txt and read it. If it is empty (which it is) it will call a method to add things into it but I keep getting EOFException. I know the file is empty but it's just a part of a programI'm working on. How to determine a file is empty without getting EOFException
try(ObjectOutputStream outManager = new ObjectOutputStream(new
FileOutputStream("manager.txt"))){
try(ObjectInputStream inManager = new ObjectInputStream(new
FileInputStream("manager.txt"))){
while(true){
manager.add((Manager)inManager.readObject());
if(manager.isEmpty()){
//A method to add
}
}catch(IOException e){
}
}catch (IOException e){
}
You can read from file as follows:
try (FileInputStream fis = new FileInputStream("manager.txt");
ObjectInputStream ois = new ObjectInputStream(fis);)
{
while (fis.available() > 0) {
Object obj = ois.readObject();
if (obj instanceof Manager) {
Manager manager = (Manager) obj;
System.out.println(manager);
}
}
} catch (IOException | ClassNotFoundException ex) {
ex.printStackTrace();
}
Basically, what you are looking for is fis.available().

reading objects from file

I have a problem with reading objects from file Java.
file is anarraylist<projet>
This is the code of saving objects :
try {
FileOutputStream fileOut = new FileOutputStream("les projets.txt", true);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
for (projet a : file) {
out.writeObject(a);
}
out.close();
} catch (Exception e) {
e.printStackTrace();
}
And this is the code of reading objects from file ::
try {
FileInputStream fileIn = new FileInputStream("les projets.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
while (in.available() > 0){
projet c = (projet) in.readObject();
b.add(c);
}
choisir = new JList(b.toArray());
in.close();
} catch (Exception e) {
e.printStackTrace();
}
Writing is working properly. The problem is the reading... it does not read any object (projet) What could be the problem?
As mentioned by EJP in comment and this SO post . if you are planning to write multiple objects in a single file you should write custom ObjectOutputStream , because the while writing second or nth object header information the file will get corrupt.
As suggested by EJP write as ArrayList , since ArrayList is already Serializable you should not have issue. as
out.writeObject(file) and read it back as ArrayList b = (ArrayList) in.readObject();
for some reason if you cant write it as ArrayList. create custome ObjectOutStream as
class MyObjectOutputStream extends ObjectOutputStream {
public MyObjectOutputStream(OutputStream os) throws IOException {
super(os);
}
#Override
protected void writeStreamHeader() {}
}
and change your writeObject as
try {
FileOutputStream fileOut= new FileOutputStream("les_projets.txt",true);
MyObjectOutputStream out = new MyObjectOutputStream(fileOut );
for (projet a : file) {
out.writeObject(a);
}
out.close();
}
catch(Exception e)
{e.printStackTrace();
}
and change your readObject as
ObjectInputStream in = null;
try {
FileInputStream fileIn = new FileInputStream("C:\\temp\\les_projets1.txt");
in = new ObjectInputStream(fileIn );
while(true) {
try{
projet c = (projet) in.readObject();
b.add(c);
}catch(EOFException ex){
// end of file case
break;
}
}
}catch (Exception ex){
ex.printStackTrace();
}finally{
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

How to write and read java serialized objects into a file

I am going to write multiple objects to a file and then retrieve them in another part of my code. My code has no error, but it is not working properly. Could you please help me find what is wrong about my code.
I read different codes from different websites, but none of them worked for me!
Here is my code to write my objects to a file:
MyClassList is an arraylist which includes objects of my class (which must be written to a file).
for (int cnt = 0; cnt < MyClassList.size(); cnt++) {
FileOutputStream fout = new FileOutputStream("G:\\address.ser", true);
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(MyClassList.get(cnt));
}
I added "true" to the constructor of the outputstream, because I want to add each object to end of the file. Is that correct?
And here is my code to read the objects from the file:
try {
streamIn = new FileInputStream("G:\\address.ser");
ObjectInputStream objectinputstream = new ObjectInputStream(streamIn);
MyClass readCase = (MyClass) objectinputstream.readObject();
recordList.add(readCase);
System.out.println(recordList.get(i));
} catch (Exception e) {
e.printStackTrace();
}
It finally prints out just one object. Now, I don't know if I am not writing correctly or reading correctly!
Why not serialize the whole list at once?
FileOutputStream fout = new FileOutputStream("G:\\address.ser");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(MyClassList);
Assuming, of course, that MyClassList is an ArrayList or LinkedList, or another Serializable collection.
In the case of reading it back, in your code you ready only one item, there is no loop to gather all the item written.
As others suggested, you can serialize and deserialize the whole list at once, which is simpler and seems to comply perfectly with what you intend to do.
In that case the serialization code becomes
ObjectOutputStream oos = null;
FileOutputStream fout = null;
try{
fout = new FileOutputStream("G:\\address.ser", true);
oos = new ObjectOutputStream(fout);
oos.writeObject(myClassList);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if(oos != null){
oos.close();
}
}
And deserialization becomes (assuming that myClassList is a list and hoping you will use generics):
ObjectInputStream objectinputstream = null;
try {
FileInputStream streamIn = new FileInputStream("G:\\address.ser");
objectinputstream = new ObjectInputStream(streamIn);
List<MyClass> readCase = (List<MyClass>) objectinputstream.readObject();
recordList.add(readCase);
System.out.println(recordList.get(i));
} catch (Exception e) {
e.printStackTrace();
} finally {
if(objectinputstream != null){
objectinputstream .close();
}
}
You can also deserialize several objects from a file, as you intended to:
ObjectInputStream objectinputstream = null;
try {
streamIn = new FileInputStream("G:\\address.ser");
objectinputstream = new ObjectInputStream(streamIn);
MyClass readCase = null;
do {
readCase = (MyClass) objectinputstream.readObject();
if(readCase != null){
recordList.add(readCase);
}
} while (readCase != null)
System.out.println(recordList.get(i));
} catch (Exception e) {
e.printStackTrace();
} finally {
if(objectinputstream != null){
objectinputstream .close();
}
}
Please do not forget to close stream objects in a finally clause (note: it can throw exception).
EDIT
As suggested in the comments, it should be preferable to use try with resources and the code should get quite simpler.
Here is the list serialization :
try(
FileOutputStream fout = new FileOutputStream("G:\\address.ser", true);
ObjectOutputStream oos = new ObjectOutputStream(fout);
){
oos.writeObject(myClassList);
} catch (Exception ex) {
ex.printStackTrace();
}
Simple program to write objects to file and read objects from file.
package program;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class TempList {
public static void main(String[] args) throws Exception {
Counter counter = new Counter(10);
File f = new File("MyFile.txt");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(counter);
oos.close();
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
Counter newCounter = (Counter) ois.readObject();
System.out.println(newCounter.count);
ois.close();
}
}
class Counter implements Serializable {
private static final long serialVersionUID = -628789568975888036 L;
int count;
Counter(int count) {
this.count = count;
}
}
After running the program the output in your console window will be 10 and you can find the file inside Test folder by clicking on the icon show in below image.
I think you have to write each object to an own File or you have to split the one when reading it.
You may also try to serialize your list and retrieve that when deserializing.
if you serialize the whole list you also have to de-serialize the file into a list when you read it back. This means that you will inevitably load in memory a big file. It can be expensive. If you have a big file, and need to chunk it line by line (-> object by object) just proceed with your initial idea.
Serialization:
LinkedList<YourObject> listOfObjects = <something>;
try {
FileOutputStream file = new FileOutputStream(<filePath>);
ObjectOutputStream writer = new ObjectOutputStream(file);
for (YourObject obj : listOfObjects) {
writer.writeObject(obj);
}
writer.close();
file.close();
} catch (Exception ex) {
System.err.println("failed to write " + filePath + ", "+ ex);
}
De-serialization:
try {
FileInputStream file = new FileInputStream(<filePath>);
ObjectInputStream reader = new ObjectInputStream(file);
while (true) {
try {
YourObject obj = (YourObject)reader.readObject();
System.out.println(obj)
} catch (Exception ex) {
System.err.println("end of reader file ");
break;
}
}
} catch (Exception ex) {
System.err.println("failed to read " + filePath + ", "+ ex);
}

How do I store an arraylist?

I am trying to store my ArrayList between runtimes. So when I enter items into the ArrayList then close the program down and then open it back up and try to search the item I put in it will still be there.
I have tried MySQL and XML but I cannot figure it out. If you could please direct me in the direction of an easy way to store ArrayList that would be amazing.
Edit:
I am trying to serialize this ArrayList:
static ArrayList<Product> Chart=new ArrayList<Product>();
with these objects:
double Total;
String name;
double quantity;
String unit;
double ProductPrice;
Look into object serialization, it sounds like exactly what you want
What is object serialization?
This allows you to write a Java object to a file and read it back in later.
Here is an example. It also zips up the file, although you don't have to do that. You can also use the stream to write to a MYSQL blob instead of a file.
public static <T> void writeToGZIP(String filename, T obj) {
ObjectOutputStream os = null;
try {
os = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream(filename)));
os.writeObject(obj);
System.out.println("Object written to " + filename);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (os != null) { os.flush(); os.close(); }
} catch (IOException e) {
e.printStackTrace();
}
}
}
#SuppressWarnings("unchecked")
public static <T> T readFromGZIP(String filename, T obj) {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new GZIPInputStream(new FileInputStream(filename)));
obj = (T) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if( ois != null ) ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return obj;
}
ObjectOutputStream and ObjectInputStream

Categories

Resources