This is my code:
FileOutputStream fos = null;
DataOutputStream dos = null;
try {
fos = new FileOutputStream(file);
dos = new DataOutputStream(fos);
.... writing to file ....
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I read that you only need to close DataOutpustStream and it will close all other streams, is this correct? Does it do any harm if i close FileOutputStream anyways? What is the best way to close streams?
No, it doesn't do any harm
You need to close them in the same order that you opened them - think of them as wrappers around each-other. If you create a FileOutputStream and then wrap that in a DataOutputStream, you should close the DataOutputStream first.
But you should use try-with-resources:
try (
final FileOutputStream fos = new FileOutputStream(file);
final DataOutputStream dos = new DataOutputStream(fos);
) {
....writing to file....
} catch (IOException e) {
e.printStackTrace();
}
And if you handle the two exceptions in the same way, you can catch the more general IOException only.
The best way to close streams is when you're using try-resource-blocks.
In most cases streams are closed in a cascading manner. For the answer you have to take a closer look into the API.
Related
Does the stream close when you use something like:
gson.toJson(obj, new FileWriter("C:\\fileName.json"));
or is it better to to this:
try (Reader reader = new FileReader("c:\\test\\staff.json")) {
// Convert JSON File to Java Object
Staff staff = gson.fromJson(reader, Staff.class);
// print staff
System.out.println(staff);
} catch (IOException e) {
e.printStackTrace();
}
I know the try block closes the stream, but does ths first example also close the stream?
Code taken from
Mkyong
Does the stream close when you use something like:
gson.toJson(obj, new FileWriter("C:\\fileName.json"));
It does not. You should close it using try-with-resources, or a try-catch-finally block.
Since JDK 7, the preferred way to close an AutoClosable is to use try-with-resources (like in your second snippet):
try (FileWriter writer = new FileWriter("C:\\fileName.json")) {
gson.toJson(obj, writer);
} catch (IOException e) {
e.printStackTrace();
}
Or you could call close() using a try-catch-finally block:
FileWriter writer = null;
try {
writer = new FileWriter("C:\\fileName.json");
gson.toJson(obj, writer);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileWriter implements AutoClosable so it needs to be closed. Not naming the variable will not close it automatically.
I need to save a java object to internal memory (a high-level collection of different server responses if to be specific). Now I use this code:
public void write(Context context) {
FileOutputStream fos = null;
try {
fos = context.openFileOutput(BACKSTACK_FILENAME, Context.MODE_PRIVATE);
} catch (FileNotFoundException e) { e.printStackTrace(); }
try {
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(backStack);
} catch (IOException e) {
L.t("failed to write backstack: " + e.toString()); e.printStackTrace();
} finally {
try { if (fos != null) fos.close(); } catch (IOException e) { }
}
}
public void read(Context context) {
FileInputStream fis = null;
try {
fis = context.openFileInput(BACKSTACK_FILENAME);
} catch (FileNotFoundException e) { e.printStackTrace();}
try {
ObjectInputStream ois = new ObjectInputStream(fis);
Deque<FragmentInfo> list = (Deque<FragmentInfo>) ois.readObject();
L.t(list.toString());
backStack = list;
} catch (IOException | ClassNotFoundException e) {
L.t("failed to read backstack" + e.toString()); e.printStackTrace();
} finally {
try { if (fis != null) fis.close(); } catch (IOException e) { }
}
}
Since we have context here, UI thread hangs(lags) white operation is performed.
And the larger object becomes, the worse it looks. So the question is:
Is there any way to save java object to internal memory asynchroneously?
Please don't recommend to use a database for such a simple task.
Saving to internal memory won't help. The real problem is that you are doing too much work on the event listener thread. You will have the same problem if you save lots of stuff to a file, a database, "internal memory" .... or to anything else. Serialization is relatively expensive no matter how you do it, and no matter where you save the results of the serialization.
The solution is to do the work using an AsyncTask.
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).
I want write list of objects into file, and then reading it one by one, and deleting respectively.
Writing and reading functions are below. For one by one reading,first I read all, then pop first, and other write to file again. it very ineffective and takes long time. So, what should I do to get better perfomance? Or maybe, there are other variant to solve this problem
public void writeToDisk(String filePath,TreeMap<String, ArrayList<Integer>> obj){
File file = new File(filePath);
FileOutputStream fout = null;
try {
fout = new FileOutputStream(file);
ObjectOutputStream o = new ObjectOutputStream(fout);
o.writeObject(obj);
o.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public TreeMap<String, ArrayList<Integer>> readFromDisk(String filePath){
TreeMap<String,ArrayList<Integer>> invertIndexMap = null;
File file = new File(filePath);
FileInputStream f;
try {
f = new FileInputStream(file);
ObjectInputStream s = new ObjectInputStream(f);
invertIndexMap = (TreeMap<String, ArrayList<Integer>>) s.readObject();
s.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return invertIndexMap;
}
I'm trying to write a file and then read it again.
My write code:
ObjectOutputStream oos = null;
FileOutputStream fout = null;
try
{
Object myObject;
fout = new FileOutputStream(new File("C:\\Foo","Bar.log"));
oos = new ObjectOutputStream(fout);
oos.writeObject(myObject);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
oos.close();
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
My reader:
FileInputStream input;
try {
input = new FileInputStream(new File("C:\\Foo\\Bar.log"));
MyFile parsedObject = MyFileFormat.MyFile.parseFrom(input);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
But I'm getting this exception on the parser:
com.google.protobuf.InvalidProtocolBufferException: Protocol message end-group tag did not match expected tag.
at com.google.protobuf.InvalidProtocolBufferException.invalidEndTag(InvalidProtocolBufferException.java:94)
Can anyone help?
You use java's ObjectOutputStream to serialize your object, but using some custom de-serialization with guava involved?
If you use ObjectOutputStream to write stuff, you should use ObjectInputStream to read it. Also, your example does not make any sense. You never initialize myObject variable in serialization snippet, this code will simply not compile.