Java Try With Resources Does Not Work For Assignment? - java

Alright, so I was just writing a quick class and I tried to use the try with resources instead of the try-catch-finally (hate doing that) method and I keep getting the error "Illegal start of type". I then turned to The Java Tutorials section on it: http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html and it showed that you can assign a new variable in the parenthesis. I'm not sure what is going on.
private static final class EncryptedWriter {
private final Path filePath;
private FileOutputStream outputStream;
private FileInputStream inputStream;
public EncryptedWriter(Path filePath) {
if (filePath == null) {
this.filePath = Paths.get(EncryptionDriver.RESOURCE_FOLDER.toString(), "Encrypted.dat");
} else {
this.filePath = filePath;
}
}
public void write(byte[] data) {
try (this.outputStream = new FileOutputStream(this.filePath.toFile())){
} catch (FileNotFoundException ex) {
Logger.getLogger(EncryptionDriver.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

This is not how try-with-resources work. You have to declare the OutputStream there only. So, this would work:
try (FileOutputStream outputStream = new FileOutputStream(this.filePath.toFile())){
The whole point of try-with-resources is to manage the resource itself. They have the task of initializing the resource they need, and then close it when the execution leaves the scope. So, it doesn't make sense for it to use the resource declared else where. Because it wouldn't be right to close the resource which it hasn't opened, and then the issue with the old try-catch is back.
The very first line of that tutorial clearly states this thing:
The try-with-resources statement is a try statement that declares one or more resources.
... and declaration is different from initialization or assignment.

Related

Java FileChannel keeps locking file

Hope someone can shed some light into what I'm doing wrong.
I have a DataLoader class that creates a FileInputStream. Since FileInputStream implements Closeable, I create that instance as part of the try block.
I then pass the newly created stream to a DataManager class. This class opens a file channel and reads data into a singleton class, storing all data into memory blocks. Since FileChannel also implements Closeable, I also instanciate it in the try block
I then invoke this code from a single thread to check every now if there are any filechanges, and when this happens, a new instance of DataLoader is created to rebuild the memory blocks. But this constantly fails due to file locking. This code is part of a Java 1.8 standard application, running on windows 10. Am I assuming wrongly that both file channel and file inputstream close? I added code to invoke the close method in both classes, but with no success. Any help would be greatly appreciated. Thanks in advance.
public class DataManager {
public DataManager(FileInputStream in) throws IOException {
fromInputStream(in);
}
public final void fromInputStream(FileInputStream in) throws IOException {
try (FileChannel ch = in.getChannel()) {
MappedByteBuffer mb = ch.map(MapMode.READ_ONLY, ch.position(), ch.size());
readData(mb); //reads mapped buffer into a byte array, e.g.: mb.get(barray, 0, 1000);
}
}
}
public class DataLoader {
public DataLoader(File binFile) throws FileNotFoundException, IOException {
try (FileInputStream in = new FileInputStream(binFile)) {
DataManager d = new DataManager(in);
} catch (Exception e) {
LOG.error("Something went wrong while loading data.", e);
}
}
}
As suggested in the comments, the issue relies on windows being somewhat stringent regarding the use of FileChannel. I replaced all FileChannel related code with InputStream and the locking behavior disappeared.

Java AutoClosable behaviour in function

I have a sample code here. Will the FileInputStream created by the function, get automatically closed when the code exists the try/catch block of parentFunction ?
Or does it need to be explicitly closed in the someOtherFunction() itself ?
private void parentFunction() {
try {
someOtherFunction();
} catch (Exception ex) {
// do something here
}
}
private void someOtherFunction() {
FileInputStream stream = new FileInputStream(currentFile.toFile());
// do something with the stream.
// return, without closing the stream here
return ;
}
You have to use the resource with try-with-resource block.
Please read docs for AutoCloseable interface: https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html
method of an AutoCloseable object is called automatically when exiting a try-with-resources block for which the object has been declared in the resource specification header.
It needs to either be explicitly closed in the someOtherFunction() method, or used in a try-with-resources block:
private void someOtherFunction() {
try (FileInputStream stream = new FileInputStream(currentFile.toFile())) {
// do something with the stream.
} // the stream is auto-closed
}

NullPointerException from PrintWriter class and File creation

I've been working on a small bit of code and though the rest of the code works, there is an error with the logging system that I've written.
When the method log(String) is called, it throws a NullPointerException.
I thought this might be because the file might not be being created, but I'm not sure what I've done wrong and as far as I can tell the file should be being created (It's not) and even if I create the file and put it into the correct position, the exception is still thrown.
I've been tinkering around with it a bit, so some of it doesn't make sense, it's probably because it was while I was debugging.
Here's the code:
package UI;
import java.io.File;
import java.io.PrintWriter;
public class InputLogger {
//Necessary for interceptor pattern
private static PrintWriter output;
//For testing remove later
private static File logFile;
public InputLogger() {
initiate("log.txt");
}
public InputLogger(String anotherFile) {
initiate(anotherFile);
}
public void initiate(String filename) {
try {
/*File */logFile = new File(filename);
if(!logFile.exists()) {
if(!logFile.createNewFile())
System.err.println("Error creating log file. Please verify that files can be created.");
}
output = new PrintWriter(logFile);
} catch (Exception e) {
System.err.println("Error accessing log file. Please verify that files can be created.");
}
}
public static void log(String action) {
try {
output.println(action);
} catch (Exception e) {
e.printStackTrace(System.out);
System.err.println("Error printing to log file. Please verify that file exists or can be created.");
}
}
public void close() {
output.close();
}
}
I think it might have something to do with the fact that I call it as a static method, but I've been looking around and I can't seem to find an explanation elsewhere.
Edit:
I forgot to actually create an InputLogger object. Thanks guys.
Most likely you forgot to create an InputLogger object. Do this:
InputLogger logger = new InputLogger();
InputLogger.log( "hoooey" );
logger.close();
Not calling close may lose a line or two.
Mixing static with a constructor and proper methods is dangerous, and an antipattern. You might remain with static, with a lazy initialization which gives your program the chance to set the file name. Or, better, avoid the statics and do all in proper methods.
In the method initiate you initialize the output, but in your static method log it's not guaranteed to have been initialized before calling since.
To be safe you should always initialize the required static variables either in the static method or as a field declaration.
In this case in your initiate it is possible to throw an exception prior to the line output = new PrintWriter(logFile) which means output is null

What is the best way to emulate try-with-resources in Java 6?

It turns out that almost nobody closes resources in Java correctly. Programmers either do not use try-finally block at all, or just put resource.close() in finally which is also incorrect (because Throwable from close() can shadow Throwable from try block). Sometimes they put something like IOUtils.closeQuietly() with is only correct for InputStream, but not for OutputStream. try-with-resources solves all of these problems but there are still huge number of projects written in Java 6.
What is the best way to emulate try-with-resources in Java 6? Now I use Guava Closer, which is better than nothing but still much uglier than try-with-resources. Also, there is a pattern called a loan-pattern, but the absence of lambdas in Java makes this pattern very cumbersome. Is there a better way?
I've found a good replacement for try-with-resources. It uses Lombok library with annotation processing:
#Cleanup InputStream in = new FileInputStream(args[0]);
#Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
However, it doesn't handle exception correctly. This bug is more than 1 year old and still is not closed: https://code.google.com/p/projectlombok/issues/detail?id=384
Though anonymous class is quite verbose, it's still acceptable in java land
new TryWithResource<InputStream>(){
protected InputStream init() throws Exception {
return new FileInputStream("abc.txt");
}
protected void use(InputStream input) throws Exception{
input.read();
}
};
----
abstract class TryWithResource<R>
{
abstract protected R init() throws Exception;
abstract protected void use(R resource) throws Exception;
// caution: invoking virtual methods in constructor!
TryWithResource() throws Exception
{
// ... code before
R r = init();
use(r);
// ... code after
}
}
If your only problem with IOUtils.closeQuietly is that it ignores exceptions on OutputStreams, then you can either simply call close() on them, or create your own utility class which automatically treats the two differently, like this:
public static void close(Closeable resource)
{
try
{
resource.close();
}
catch(Exception e)
{
//swallow exception
}
}
public static void close(OutputStream o)
{
//throw any exceptions
o.close();
}
The correct overloaded method will be selected at compile time in all common situations, although if you're passing OutputStreams around as Closeables then you'll have to change this to do a dynamic instanceof check to make sure OutputStreams always throw exceptions.

BufferedWriter - Stream closed prematurely during program execution

I am defining a buffered writer in a class I am developing, but having problems with it.
In the class constructor I am defining:
public class RestHandler {
public static BufferedWriter rest_logger;
public RestHandler(parsedXMLConfigData _config, BufferedWriter writer) {
rest_logger = writer;
try {
rest_logger.write("RestHandler instance finished init and ready to receive calls!" + "\n");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
This works and prints the text to my file. But when I try to use the same rest_logger in another one of my class methods:
#POST
#Path("{subResources: [a-zA-Z0-9_/]+}")
public void postHandler
(
#Context final UriInfo uriInfo,
#PathParam("subResources") String subResources) {
try {
rest_logger.write("TEXT...");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
It gives me a stream closed exception! I should mention that I use this to close the stream:
protected void finalize() throws Throwable {
rest_logger.close();
}
There are several problems with your code:
the rest_logger variable should not be static
you shouldn't initialize it to a new BufferedWriter just to discard it afterwards and reinitialize it with the writer argument (that you have no control on)
you shouldn't ignore exceptions. If you don't know what to do with them, make your methods throw IOException and let the caller decide what to do
you should not use finalizers
you should not close a writer that you have not created. Let the opener of the writer close it.
Other than that, and since your code doesn't make much sense, it's hard to understand what the code is supposed to do.
Removing the exception handlers for clarity, your code does:
rest_logger = new BufferedWriter(new FileWriter("rest_logger.txt"));
rest_logger = writer;
You're throwing away that new BufferedWriter immediately there. It does not make much sense. rest_logger will be set to whatever was handed over to you in that constructor call. When that gets closed, rest_logger will be closed too.
I'm not quite sure I understood your question, BUT:
why exactly are you overwriting your newly created BufferedWriter?
rest_logger = writer;
maybe you should look into that...

Categories