I'm trying to copy a file with .dat extension from a certain directory decided by the user into the project directory. When I try to read the saved object selected by the user, the program always gives IOException.
File f = new File(chooser.getSelectedFile().getPath());
if(f.exists() && !f.isDirectory()) {
FileInputStream flusso= null;
ObjectInputStream leggiObj=null;
try {
flusso = new FileInputStream(chooser.getSelectedFile().getPath());
System.out.println(chooser.getSelectedFile().getPath());
leggiObj = new ObjectInputStream(flusso);
if (leggiObj.readObject().getClass().equals(DatiProgresso.class)) {
DatiProgresso dp = (DatiProgresso) leggiObj.readObject();//<----THIS LINE GIVES THE EXEPTION
leggiObj.close();
flusso.close();
System.out.println("Ciao");
FileOutputStream fop = new FileOutputStream("salvataggi/" + dp.getNome() + ".dat");
ObjectOutputStream scriviObj = new ObjectOutputStream(fop);
scriviObj.writeObject(dp);
scriviObj.flush();
fop.close();
} else {
JOptionPane.showMessageDialog(this, "Unacceptable file", "Error", JOptionPane.ERROR_MESSAGE);
}
} catch (HeadlessException ex) {
System.out.println("HeadlessException");
ex.printStackTrace();
} catch (FileNotFoundException ex) {
System.out.println("FileNotFoundException");
ex.printStackTrace();
} catch (IOException ex) {
System.out.println("IOException");
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
System.out.println("ClassNotFoundException");
ex.printStackTrace();
}
}
}
else
{
JOptionPane.showMessageDialog(this, "Unacceptable file", "Error" ,JOptionPane.ERROR_MESSAGE);
}
DatiProgresso dp = (DatiProgresso) leggiObj.readObject();
This line gives the exception.
leggiObj.readObject().getClass().equals(DatiProgresso.class) - here you read your object from the data stream. On next line you attempt to read 2nd object from the stream. If there is no another object then stream fails.
I create a client similarity, where clients register an account (an object is created) which is stored in a file.
Objects are written to the file as required, I override the writeStreamHeader() method. But when I try to read them all, their file throws an exception.
Write the objects to the file here.
public static void saveAccaunt(LoginAndPass gamers) {
boolean b = true;
FileInputStream fis = null;
try{
fis = new FileInputStream("student.ser");
fis.close();
}
catch (FileNotFoundException e)
{
b = false;
} catch (IOException e) {
e.printStackTrace();
}
try {
FileOutputStream fileOutputStream = new FileOutputStream("student.ser",true);
ObjectOutputStream os = null;
if(b = true){
os = new AppendingObjectOutputStream(fileOutputStream);
System.out.println("Объект добавлен!");
}else {
os = new ObjectOutputStream(fileOutputStream);
System.out.println("Создан");
}
os.writeObject(gamers);
os.close();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream("student.ser");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
test = new ArrayList<>();
while (true){
test.add(objectInputStream.readObject());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(test.get(0));
}
Here is the error log for the exception thrown:
java.io.StreamCorruptedException: invalid stream header: 79737200
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:866)
at java.io.ObjectInputStream.(ObjectInputStream.java:358)
at Registratsiya.AllGamers.main(AllGamers.java:48)
Exception in thread "main" java.lang.NullPointerException
at Registratsiya.AllGamers.main(AllGamers.java:61)
when I use readObject I get OptionalDataException (An attempt was made to read an object when the next element in the stream is primitive data), how do I fix this? Page is Serializable. writeObject works.
public Map<Long,Page<byte[]>> readAllPages(){
ObjectInputStream in = null;
try
{
in= new ObjectInputStream(new FileInputStream(HardDisk.getDefault_File_Name()));
#SuppressWarnings("unchecked")
Map<Long, Page<byte[]>> readMap = (Map<Long, Page<byte[]>>)in.readObject(); // exception here
return readMap;
}
catch(Exception ex)
{
ex.printStackTrace();
System.exit(0);
return null;
}
finally
{
if(in != null)
{
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void writeAllPages(Map<Long,Page<byte[]>> hd){
ObjectOutputStream out = null;
try
{
out = new ObjectOutputStream(new FileOutputStream(HardDisk.getDefault_File_Name()));
out.writeObject(hd);
}
catch(Exception ex)
{
ex.printStackTrace();
System.exit(0);
}
finally
{
if(out != null)
{
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The problem was that the class that has the read method extends ObjectInputStream so I shouldn't also create the "in" object, I deleted it and exchanged it with "this" and the problem was solved!
I have a class PDF which implements an interface fileReader.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class PDF implements fileReader {
#Override
public byte[] readFile(File pdfDoc) {
if (!pdfDoc.exists()) {
System.out.println("Could not find" + pdfDoc.getName() + " on the specified path");
return null;
}
FileInputStream fin = null;
try {
fin = new FileInputStream(pdfDoc);
} catch (FileNotFoundException e) {
System.out.println("");
e.printStackTrace();
}
byte fileContent[] = new byte[(int) pdfDoc.length()];
try {
fin.read(fileContent);
} catch (IOException e) {
e.printStackTrace();
}
return fileContent;
}
}
import java.io.File;
public interface fileReader {
<T> T readFile(File fileObject);
}
I notice that there are scope issues for variables fin.
Another implementation I made was:
public byte[] readFile1(File pdfDoc) {
if (!pdfDoc.exists()) {
System.out.println("Could not find" + pdfDoc.getName() + " on the specified path");
return null;
}
FileInputStream fin = null;
try {
fin = new FileInputStream(pdfDoc);
byte fileContent[] = new byte[(int) pdfDoc.length()];
try {
fin.read(fileContent);
} catch (IOException e) {
System.out.println("");
e.printStackTrace();
}
} catch (FileNotFoundException e) {
System.out.println("");
e.printStackTrace();
}
return fileContent;
}
But now I could not access fileContent.
How can I combine the try-catches so that I don't have scope problems?
Can there be a better design approach to this problem? I have to make functions for reading three different types of file.
Since Java 7 you can combine the try-catch as follows:
FileInputStream fin = null;
try {
fin = new FileInputStream(pdfDoc);
byte fileContent[] = new byte[(int) pdfDoc.length()];
fin.read(fileContent);
} catch (IOException | FileNotFoundException e) {
System.out.println("");
e.printStackTrace();
}
Which, in my opinion, makes the code cleaner and variable scopes more obvious.
You can nest the try catch statements:
try {
FileInputStream fin = new FileInputStream(pdfDoc);
byte fileContent[] = new byte[(int) pdfDoc.length()];
try {
fin.read(fileContent);
return fileContent;
} catch (IOException e) {
e.printStackTrace();
} finally {
fin.close();
}
} catch (FileNotFoundException e) {
System.out.println("");
e.printStackTrace();
}
return null;
Note that I added a close() in a finally clause to clean up. And also returning null is probably not what you want in case of error, but that's application specific.
You can have one try with multiple catch blocks.
try {
//do stuff
}
catch (FileNotFoundException e) {
System.out.println("");
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
You can modify this part:
FileInputStream fin = null;
try {
fin = new FileInputStream(pdfDoc);
} catch (FileNotFoundException e) {
System.out.println("");
e.printStackTrace();
}
byte fileContent[] = new byte[(int) pdfDoc.length()];
try {
fin.read(fileContent);
} catch (IOException e) {
e.printStackTrace();
}
By
{
......
FileInputStream fin = null;
byte fileContent[]=null;
try {
fin = new FileInputStream(pdfDoc);
fileContent = new byte[(int) pdfDoc.length()];
fin.read(fileContent);
} catch (FileNotFoundException e) {
System.out.println("");
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
return fileContent
}
I would write like this:
public byte[] readFile(File pdfDoc) {
if (!pdfDoc.exists()) {
System.out.println("Could not find" + pdfDoc.getName() + " on the specified path");
return null;
}
FileInputStream fin = null;
byte fileContent[] = new byte[(int) pdfDoc.length()];
try {
fin = new FileInputStream(pdfDoc);
fin.read(fileContent);
} catch (FileNotFoundException e) {
System.out.println("");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != fin) {
fin.close();
}
}
return fileContent;
}
Since Java 7, there is a nice utility methods for reading the entire content of a file:
return Files.readAllBytes(pdfFile.toPath());
This method will open and close the FileInputStream for you, so you don't need to do this yourself. It throws an IOException if something goes wrong. Usually, it's best to let this exception propagate to the caller, but if you really want to return null in that case, you can accomplish this as follows:
try {
return Files.readAllBytes(pdfFile.toPath());
} catch (IOException e) {
e.printStackTrace();
return null;
}
This also has the nice advantage that the value returned in that case is explicit - or did you really mean to return an array filled with 0 values if the file could no longer be found, as your current code does?
Note that since NoSuchFileException is a subclass of IOException, the catch block will handle both. If you want to handle it differently you can write a separate catch block for the NoSuchFileException:
try {
return Files.readAllBytes(pdfFile.toPath());
} catch (NoSuchFileException e) {
System.err.println("Oh no, the file has disappeared.");
e.printStackTrace();
return null;
} catch (IOException e) {
System.err.println("The file exists, but could not be read.");
e.printStackTrace();
return null;
}
Finally, I should probably mention that your file reading code is incorrect, as InputStream.read() does not necessarily read the entire file at once. That's why it returns the number of bytes read so you can invoke it again for the rest of the file. But as I said, since Java 7 you don't need to use such low level APIs (unless the file is too big to fit into memory, of course).
When I want to close InputFileStream and OutputFileStream objects, eclipse says that I need to catch IOException so here is my code after catching those exceptions.
As you can see I am catching IOException twice. Is there a more simple way that I can have only one block for catching IOException for both in.close() and in.read() ?
public class ByteStream {
public static void main(String[] args) {
FileInputStream in = null;
try {
in = new FileInputStream("testdata.txt");
int nextByte;
while((nextByte = in.read()) != -1){
System.out.println(nextByte + "-");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null){
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Use the try-with-resources syntax in Java 7
try (FileInputStream in = new FileInputStream("testdata.txt");){
int nextByte;
while ((nextByte = in.read()) != -1) {
System.out.println(nextByte + "-");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
the compiler will take care of converting the above code to code that closes the in InputStream, or any other AutoCloseable object declared and instatiated in the () part of the try expression.