Java: Does nu.xom.Builder properly close Files? - java

I am using nu.xom.* for my project, link found at http://www.xom.nu/. My question is about the following part of my code:
private void open() {
builder = new Builder();
try {
document = builder.build(file);
} catch (ParsingException | IOException ex) {
Logger.getLogger(InvoiceData.class.getName()).log(Level.SEVERE, null, ex);
}
}
I have some unwanted file locks in my program and am practically checking all places where I open a file. Now it struck me here that builder.build(File file) does implement Closeable, so I myself am not sure here whether it closes the file properly or not.
Can anyone shed some light on this?
Regards.

Fortunately the XOM library is open source, so you can take a look at the source code of nu.xom.Builder.build(File):
public Document build(File in)
throws ParsingException, ValidityException, IOException {
InputStream fin = new FileInputStream(in);
// [...]
String base = url.toString();
try {
Document doc = build(fin, base);
return doc;
}
finally {
fin.close();
}
}
So you pass a File instance to the build() method and inside this method a FileInputStream is opened and closed at the end.
There is a part after new FileInputStream(in) which is not enclosed by a try block. If this code throws an unchecked exception it is possible that the input stream isn't closed. But if you don't catch an exception then you can be sure, that the input stream is closed properly.

Related

how to return FileInputStream ?? in java [duplicate]

This question already has answers here:
Java return value (in try/catch clause)
(6 answers)
Closed 2 years ago.
package asasaSASA;
import java.io.*;
class FileInputTest {
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis; // I HAVE RETURN fis
}
catch (FileNotFoundException e) {
System.out.println("에러는"+e);
}
}
public static void main(String args[]) {
FileInputStream fis1 = null;
String fileName = "foo.bar";
System.out.println("main: Starting " + FileInputTest.class.getName()
+ " with file name = " + fileName);
fis1 = f1(fileName);
System.out.println("main: " + FileInputTest.class.getName() + " ended");
}
}
I want to make this code run but it said
This method must return a result of type FileInputStream
I can't understand because I made return fis. Why does it say that you have to return? I already returned it!
FileInputStream fis = new FileInputStream(fileName);
If the above line throws a FileNotFoundException then the next line of your code that will be executed is
System.out.println("에러는"+e);
which means it bypasses your return statement and that's why you are getting the compiler error.
There are many different ways to fix the compiler error and the other answers explain the different ways. I'm just answering your question, namely
Why does it say that you have to return?
I hope you understand now why you are wrong when you say
I already returned it!
Your exception handling is the problem. It's common, but bad code style: Whenever you catch an exception, the right move is to either deal with that exception, or, to ensure that you (re)throw some exception.
Log it, or print it? That is not handling an exception.
In this case, 'file not found' is not something you can be expected to handle; not unless you expand on what f1 is supposed to do (tip: Methods should be a bit more descriptive than that). Thus, throwing something is fair game. Furthermore, the very definition of f1 (presumably; that name is not particular enlightening and the method has no documentation) suggests that 'open this file' is a fundamental aspect of it, and therefore, throwing a FileNotFoundException is fair as well.
Thus:
Best solution
public static FileInputStream f1(String fileName) throws IOException {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
}
public static void main(String[] args) throws Exception {
String fileName = "foo.bar";
System.out.println("main: Starting " + FileInputTest.class.getName()
+ " with file name = " + fileName);
try (InputStream in = f1(fileName)) {
// you must close any resources you open using a try-with-resources
// construct; you did not do that in your code, I fixed this.
}
}
NB: your psv main can (and generally should!) be declared to throws Exception.
Alternate take
This one works in any scenario where you cannot throws the exception, or if adding that the signature makes no sense because it reflects an implementation detail and not an inherent aspect of what the method is trying to do:
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
} catch (IOException e) {
throw new RuntimeException("Unhandled", e);
}
}
Naturally, this is only appropriate for situations where you really don't expect that exception to occur under normal circumstances. Otherwise, either throw that exception onwards or make your own exception type and throw that instead of RuntimeException.
If you just need a ¯\(ツ)/¯ I don't really know what this means, I just want to move on and get rid of these exceptions solution: throw new RuntimeException("Uncaught", e); is correct; e.printStackTrace(); is incorrect. Update your IDE's templates.
Your method throws a checked exception which must be handled either inside of the method, or outside. Checked exception are to indicate that a problem may occur and you need to implement something to handle this scenario. Here we are worried that the file does not exist.
You have three Choices:
Return and handle value for not existing file (no exception is thrown here). So either return null, then check in main() that inputStream is not null, or return Optional<>, which is a JDK8 way to handle such scenarios.
Example:
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
} catch(FileNotFoundException e) {
System.out.println("Error "+e);
return null; // in case of not existing file
}
}
Wrap your checked FileNotFoundException into a custom RuntimeException. This will solve your problem with compile error, but may cause problems in the future if you will not catch this exception somewhere.
Example:
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
} catch(FileNotFoundException e) {
System.out.println("Error "+e);
throw new RuntimeException(e);
}
}
Instead of try-catch add this exception to your method signature:
Example:
public static FileInputStream f1(String fileName) throws FileNotFoundException{
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
}
But if you declare a checked exception in a method at some point you will have to catch it and handle.
Option 3 is most desired.

Java: Why does an unclosed stream not throw an exception?

I wanted to write to a property file. But it silently never worked. Just from the code behavior I could not notice it. I always had to open the properties file and look if the value changed. But it never did. So actually I would expect to get an exception . The problem seemed to be that I did not close the InputStream before opening the OutputStream. But I never got to know that. It cost me 3 days because I would expect either OutputStream or store function to give me some feedback. Have a look at the code.
File file = ResourceUtils.getFile("classpath:First.properties");
FileInputStream in = new FileInputStream(file);
Properties props = new Properties();
props.load(in);
System.out.println(props.getProperty("country"));
in.close(); // This I always forgot
FileOutputStream out = new FileOutputStream(file);
props.setProperty("country", "germany");
props.store(out, null);
System.out.println(props.getProperty("country"));
out.close();
As for the actual question "why does it not throw an exception", it's because there are cases you want the Stream to remain open.
class FileWriteSample implements Closeable {
FileOutputStream writeTo;
public FileWriteSample(String filename) throws IOException {
writeTo = new FileOutputStream(filename);
// should we expect an Exception here because we don't close the Stream?
// we're planning to use it later on
}
public void write(String s) {
// write to stream
}
public void close() throws IOException {
writeTo.close();
}
}
A forgotten close() statement cannot cause an exception. From the perspective of your stream everything is okay. It just didn't wrote to its destination yet. Why should it? Even when the whole program terminates there is no guaranty that the stream closes and writes its internal buffers out.[1]
You always have to call flush() or close() actively. The underlying implementation will then perform the actual write operation.
This mistake is so common that there is an extra Java-Feature to handle it. It is called try-with-resources and prevents programmers from the evil consequences of missing close() statements.
Example:
//use try-with-resources on out
private void saveProperties(Properties properties, String path) {
try(PrintStream out = new PrintStream(new FileOutputStream(path))) {
printProperties(properties,out);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// you can pass System.out as well to print to console
private void printProperties(Properties properties, PrintStream out) {
try {
properties.store(out, null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//properties.load leaves the stream open, so you have to use try-with-resources
private Properties readProperties(String path) {
try (FileInputStream in = new FileInputStream(path)) {
Properties properties = new Properties();
properties.load(in);
return properties;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Related posts on Java Properties:
Read properties from outside of a jar: https://stackoverflow.com/a/54766296/1485527
Sorted print of properties: https://stackoverflow.com/a/54781548/1485527
Related posts on Java Streams:
Closing Streams in Java
[1] See: Josh Bloch, Effective Java,(2nd ed.), Page 27.
Avoid finalizers.[...] It is entirely possible, even likely, that a program terminates without executing finalizers on some objects that are no longer reachable.

Unable to move a file using java while using apache tika

I am passing a file as input stream to parser.parse() method while using apache tika library to convert file to text.The method throws an exception (displayed below) but the input stream is closed in the finally block successfully. Then while renaming the file, the File.renameTo method from java.io returns false. I am not able to rename/move the file despite successfully closing the inputStream. I am afraid another instance of file is created, while parser.parse() method processess the file, which doesn't get closed till the time exception is throw. Is that possible? If so what should I do to rename the file.
The Exception thrown while checking the content type is
java.lang.NoClassDefFoundError: Could not initialize class com.adobe.xmp.impl.XMPMetaParser
at com.adobe.xmp.XMPMetaFactory.parseFromBuffer(XMPMetaFactory.java:160)
at com.adobe.xmp.XMPMetaFactory.parseFromBuffer(XMPMetaFactory.java:144)
at com.drew.metadata.xmp.XmpReader.extract(XmpReader.java:106)
at com.drew.imaging.jpeg.JpegMetadataReader.extractMetadataFromJpegSegmentReader(JpegMetadataReader.java:112)
at com.drew.imaging.jpeg.JpegMetadataReader.readMetadata(JpegMetadataReader.java:71)
at org.apache.tika.parser.image.ImageMetadataExtractor.parseJpeg(ImageMetadataExtractor.java:91)
at org.apache.tika.parser.jpeg.JpegParser.parse(JpegParser.java:56)
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:244)
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:244)
at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:121)
Please suggest any solution. Thanks in advance.
public static void main(String args[])
{
InputStream is = null;
StringWriter writer = new StringWriter();
Metadata metadata = new Metadata();
Parser parser = new AutoDetectParser();
File file = null;
File destination = null;
try
{
file = new File("E:\\New folder\\testFile.pdf");
boolean a = file.exists();
destination = new File("E:\\New folder\\test\\testOutput.pdf");
is = new FileInputStream(file);
parser.parse(is, new WriteOutContentHandler(writer), metadata, new ParseContext()); //EXCEPTION IS THROWN HERE.
String contentType = metadata.get(Metadata.CONTENT_TYPE);
System.out.println(contentType);
}
catch(Exception e1)
{
e1.printStackTrace();
}
catch(Throwable t)
{
t.printStackTrace();
}
finally
{
try
{
if(is!=null)
{
is.close(); //CLOSES THE INPUT STREAM
}
writer.close();
}
catch(Exception e2)
{
e2.printStackTrace();
}
}
boolean x = file.renameTo(destination); //RETURNS FALSE
System.out.println(x);
}
This might be due to other processes are still using the file, like anti-virus program and also it may be a case that any other processes in your application may possessing a lock.
please check that and deal with that, it may solve your problem.

Can't delete the file after writing some data to it, where is wrong?

I'm write some text a file then delete it, but the deletion is failed.
The code is very simple:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class TestFile {
public static void main(String[] args) throws IOException {
File file = new File("c:\\abc.txt");
writeFile(file, "hello");
// delete the file
boolean deleted = file.delete();
System.out.println("Deleted? " + deleted);
}
public static void writeFile(File file, String content) throws IOException {
OutputStream out = null;
try {
out = new FileOutputStream(file);
out.write(content.getBytes("UTF-8"));
} catch (IOException e) {
try {
out.close();
} catch (IOException e1) {
// ignored
}
}
}
}
The output is:
Deleted? false
And there is a file abc.txt contains hello still there under c:.
Then I use FileUtils.writeStringToFile(...) from commons-io.jar instead, the file will be deleted.
But I don't know where is wrong with my code, please help me to find it out.
You are only closing the file if you get an IOException.
Change it to a finally block and you will be able to close and delete the file.
public static void writeFile(File file, String content) throws IOException {
OutputStream out = new FileOutputStream(file);
try {
out.write(content.getBytes("UTF-8"));
} finally {
try {
out.close();
} catch (IOException ignored) {
}
}
}
You need to close your OutputStream when you finished writing the file.
try {
out = new FileOutputStream(file);
out.write(content.getBytes("UTF-8"));
out.close();
} catch (IOException e) {
try {
out.close();
} catch (IOException e1) {
// ignored
}
}
In your main method,
public static void main(String[] args) throws IOException {
File file = new File("c:\\abc.txt");
writeFile(file, "hello");
// delete the file
boolean deleted = file.delete();
System.out.println("Deleted? " + deleted);
}
You open the file, write to it and then do not close it. Java keeps the file open for you, so if you wanted to add more information to it, you could. However, to be able to delete the file, you need to make sure no other reference is open to it. You can do this by using file.close() to close the file handle Java reserves for you.
It's best practice to always close a stream when you are done with it, especially if you added data to it. Otherwise, you might run into situations where you are keepings files open by accident, or, in extreme cases, lose data you thought was saved already.
Have a look at what FileUtils.writeStringToFile() does that you haven't.
public static void writeStringToFile(File file, String data, String encoding) throws IOException {
OutputStream out = new java.io.FileOutputStream(file);
try {
out.write(data.getBytes(encoding));
} finally {
IOUtils.closeQuietly(out);
}
}
You will note that the out stream is always closed, wheras in your example it only gets closed in your catch block if the write() throws an exception.
On Windows, files that are open by any program cannot be deleted.
You just delete your file if an exception occurs. You need to do that every time, after you opened the file.
You may want to put close into a finally block.
If you're using Java 7 I consider using a try-with-ressources block, which takes care of closing files for you.
try (BufferedReader br = new BufferedReader(new FileReader(path)))
{
return br.readLine();
}

Assistance in writing my file writer method for a servlet

I have a simple servlet where I write to a file if it has a queryparameter 'hello', and since this is a test I want to display the error the the webpage also.
IntelliJ is complaining that I am not catching the IOException, not sure what's wrong:
private static void WriteToFile(String filePath, String fileName, String fileData) {
FileWriter writer = null;
try {
writer = new FileWriter(fileName);
writer.write(fileData);
} catch(IOException ex) {
} finally {
if(writer != null) {
writer.close();
}
}
}
Also, in my exception, I noticed on the web most people write:
How can I output the error to the web page?
You're not catching IOException when you call writer.close(); in the finally block.
You're also completely swallowing any IOException thrown in the main code, which is a really bad idea. If something's goes wrong, you'll have no idea what's happening.
I would personally suggest that you let that method throw the exception to the caller:
private static void writeToFile(String filePath, String fileName,
String fileData) throws IOException {
FileWriter writer = new FileWriter(fileName);
try {
writer.write(fileData);
} finally {
writer.close();
}
}
Note that if the try block throws an exception and the finally block does, you'll effectively "lose" the original exception. You may want to suppress exceptions throw when closing.
Or just use Guava which makes all of this simpler anyway with its Files class.
Or if you're using Java 7, you could use a try-with-resources statement.
(I note that you're ignoring filePath by the way - why?)
You can write in catch block too : writer.write(errorMessage);
or you may redirect to Error page if error occured

Categories