I've encountered an issue in Java trying to write to a file using FileWriter. Simply declaring FileWriter writer = new FileWriter("filelocation"); yields that there is an unreported IOException which must be caught.
To rectify this, naturally I put my FileWriter within a try-catch block, but that causes an issue with scope. To fix this, I tried declaring the FileWriter before the try catch block and assigning the location within the try catch. After the try catch block when I would like to use the FileWriter, it tells me it may not have been initialized. I'm not certain how else to handle this, and never encountered this issue in Java 1.7 or likewise.
This is an example of my final situation in case I was unclear;
Scanner userInput = new Scanner(System.in);
FileWriter writer;
try {
System.out.println("Enter the file directory you would like to store in");
String fileLocation = userInput.nextLine();
writer = new FileWriter(fileLocation);
} catch(java.io.IOException e) {
System.out.println("Error message");
}
writer.write("Stuff"); //writer may not have been initialized
The good way :
System.console().printf("Enter the file directory you would like to store in");
String location = System.console().readLine();
try (FileWriter writer = new FileWriter (location)) {
writer.write("Stuff");
} catch (IOException e) {
new RuntimeException("Error message", e).printStackTrace();
}
Explanations:
System.console().printf() enable to print message on stdout. System.out may be prefered is having a "console" is not strictly required.
Uses System.console() for console management. Much easier and clearer. Don't forget to allocate a console (ie don't use javaw executable).
Opens stream using try-with-resources statement
printStackTrace() print on stderr the call stack which ease finding error location in code.
I have built a new Exception to attach your error message with the stack trace adds the "catch" location in the stack.
Advices:
Uses byte-stream for file access (ie FileOutputStream). It enables to enforce charset (ie OutputStreamWriter) and buffering (ie BufferedOutputStream or BufferedWriter).
Using byte-stream makes also possible to switch to NIO Channel API.
Uses StandardCharsets to access default (and largely commonly used) charset (Charsets that all JVM implementations must support)
Read The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
call to printStackTrace() isn't really nice and you should quickly introduce a logging system to print messages.
In case of a CLI, have good attention when using logging system to not confuse user about system interactions (ie prompt for user input) and feedbacks (ie progress message)
You say "naturally" you put it within a try-catch block. There's nothing natural about that, since there are two ways to handle it, and the other way is more common:
Handle the exception in a try-catch block.
Don't handle the exception, but declare that your method throws the exception, and allow it to cascade up the call stack.
Your code looks like it's in a main method, so you could add throws IOException:
public static void main(String[] args) throws IOException {
In your particular case, however, you're getting the file location from a user prompt, so rather than letting the program die with an error, the appropriate thing would be to tell the user about the error and prompt for a new name.
Also, remember to close your resources.
public static void main(String[] args) throws IOException {
Scanner userInput = new Scanner(System.in);
FileWriter writer;
do {
System.out.println("Enter the file name you would like to store in");
String fileLocation = userInput.nextLine();
if (fileLocation.trim().isEmpty())
return; // Exit program when user pressed enter with a name
try {
writer = new FileWriter(fileLocation);
} catch(java.io.IOException e) {
System.out.println("Cannot write to file: " + e);
writer = null;
}
} while (writer == null);
try {
writer.write("Stuff"); //writer may not have been initialized
} finally {
writer.close();
}
}
The write and the close can still technically throw an error (e.g. disk full), which we allow to cascade and kill the program.
The Java 7 try-with-resources syntax (also known as ARM block (Automatic Resource Management)) is nice, short and straightforward when using only one AutoCloseable resource. However, I am not sure what is the correct idiom when I need to declare multiple resources that are dependent on each other, for example a FileWriter and a BufferedWriter that wraps it. Of course, this question concerns any case when some AutoCloseable resources are wrapped, not only these two specific classes.
I came up with the three following alternatives:
1)
The naive idiom I have seen is to declare only the top-level wrapper in the ARM-managed variable:
static void printToFile1(String text, File file) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
This is nice and short, but it is broken. Because the underlying FileWriter is not declared in a variable, it will never be closed directly in the generated finally block. It will be closed only through the close method of the wrapping BufferedWriter. The problem is, that if an exception is thrown from the bw's constructor, its close will not be called and therefore the underlying FileWriter will not be closed.
2)
static void printToFile2(String text, File file) {
try (FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
Here, both the underlying and the wrapping resource are declared in the ARM-managed variables, so both of them will certainly be closed, but the underlying fw.close() will be called twice: not only directly, but also through the wrapping bw.close().
This should not be a problem for these two specific classes that both implement Closeable (which is a subtype of AutoCloseable), whose contract states that multiple calls to close are permitted:
Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.
However, in a general case, I can have resources that implement only AutoCloseable (and not Closeable), which doesn't guarantee that close can be called multiple times:
Note that unlike the close method of java.io.Closeable, this close method is not required to be idempotent. In other words, calling this close method more than once may have some visible side effect, unlike Closeable.close which is required to have no effect if called more than once. However, implementers of this interface are strongly encouraged to make their close methods idempotent.
3)
static void printToFile3(String text, File file) {
try (FileWriter fw = new FileWriter(file)) {
BufferedWriter bw = new BufferedWriter(fw);
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
This version should be theoretically correct, because only the fw represents a real resource that needs to be cleaned up. The bw doesn't itself hold any resource, it only delegates to the fw, so it should be sufficient to only close the underlying fw.
On the other hand, the syntax is a bit irregular and also, Eclipse issues a warning, which I believe is a false alarm, but it is still a warning that one has to deal with:
Resource leak: 'bw' is never closed
So, which approach to go for? Or have I missed some other idiom that is the correct one?
Here's my take on the alternatives:
1)
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(text);
}
For me, the best thing coming to Java from traditional C++ 15 years ago was that you could trust your program. Even if things are in the muck and going wrong, which they often do, I want the rest of the code to be on best behaviour and smelling of roses. Indeed, the BufferedWriter might throw an exception here. Running out of memory wouldn't be unusual, for instance. For other decorators, do you know which of the java.io wrapper classes throw a checked exception from their constructors? I don't. Doesn't do code understandability much good if you rely upon that sort of obscure knowledge.
Also there's the "destruction". If there is an error condition, then you probably don't want to be flushing rubbish to a file that needs deleting (code for that not shown). Although, of course, deleting the file is also another interesting operation to do as error handling.
Generally you want finally blocks to be as short and reliable as possible. Adding flushes does not help this goal. For many releases some of the buffering classes in the JDK had a bug where an exception from flush within close caused close on the decorated object not be called. Whilst that has been fixed for some time, expect it from other implementations.
2)
try (
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw)
) {
bw.write(text);
}
We're still flushing in the implicit finally block (now with repeated close - this gets worse as you add more decorators), but the construction is safe and we have to implicit finally blocks so even a failed flush doesn't prevent resource release.
3)
try (FileWriter fw = new FileWriter(file)) {
BufferedWriter bw = new BufferedWriter(fw);
bw.write(text);
}
There's a bug here. Should be:
try (FileWriter fw = new FileWriter(file)) {
BufferedWriter bw = new BufferedWriter(fw);
bw.write(text);
bw.flush();
}
Some poorly implemented decorators are in fact resource and will need to be closed reliably. Also some streams may need to be closed in a particular way (perhaps they are doing compression and need to write bits to finish off, and can't just flush everything.
Verdict
Although 3 is a technically superior solution, software development reasons make 2 the better choice. However, try-with-resource is still an inadequate fix and you should stick with the Execute Around idiom, which should have a clearer syntax with closures in Java SE 8.
The first style is the one suggested by Oracle. BufferedWriter doesn't throw checked exceptions, so if any exception is thrown, the program is not expected to recover from it, making resource recover mostly moot.
Mostly because it could happen in a thread, with the thread dieing but the program still continuing -- say, there was a temporary memory outage that wasn't long enough to seriously impair the rest of the program. It's a rather corner case, though, and if it happens often enough to make resource leak a problem, the try-with-resources is the least of your problems.
Option 4
Change your resources to be Closeable, not AutoClosable if you can. The fact that the constructors can be chained implies it isn't unheard of to close the resource twice. (This was true before ARM too.) More on this below.
Option 5
Don't use ARM and code very carefully to ensure close() isn't called twice!
Option 6
Don't use ARM and have your finally close() calls in a try/catch themselves.
Why I don't think this problem is unique to ARM
In all these examples, the finally close() calls should be in a catch block. Left out for readability.
No good because fw can be closed twice. (which is fine for FileWriter but not in your hypothetial example):
FileWriter fw = null;
BufferedWriter bw = null;
try {
fw = new FileWriter(file);
bw = new BufferedWriter(fw);
bw.write(text);
} finally {
if ( fw != null ) fw.close();
if ( bw != null ) bw.close();
}
No good because fw not closed if exception on constructing a BufferedWriter. (again, can't happen, but in your hypothetical example):
FileWriter fw = null;
BufferedWriter bw = null;
try {
fw = new FileWriter(file);
bw = new BufferedWriter(fw);
bw.write(text);
} finally {
if ( bw != null ) bw.close();
}
To concur with earlier comments: simplest is (2) to use Closeable resources and declare them in order in the try-with-resources clause. If you only have AutoCloseable, you can wrap them in another (nested) class that just checks that close is only called once (Facade Pattern), e.g. by having private bool isClosed;. In practice even Oracle just (1) chains the constructors and doesn't correctly handle exceptions partway through the chain.
Alternatively, you can manually create a chained resource, using a static factory method; this encapsulates the chain, and handle cleanup if it fails part-way:
static BufferedWriter createBufferedWriterFromFile(File file)
throws IOException {
// If constructor throws an exception, no resource acquired, so no release required.
FileWriter fileWriter = new FileWriter(file);
try {
return new BufferedWriter(fileWriter);
} catch (IOException newBufferedWriterException) {
try {
fileWriter.close();
} catch (IOException closeException) {
// Exceptions in cleanup code are secondary to exceptions in primary code (body of try),
// as in try-with-resources.
newBufferedWriterException.addSuppressed(closeException);
}
throw newBufferedWriterException;
}
}
You can then use it as a single resource in a try-with-resources clause:
try (BufferedWriter writer = createBufferedWriterFromFile(file)) {
// Work with writer.
}
The complexity comes from handling multiple exceptions; otherwise it's just "close resources that you've acquired so far". A common practice seems to be to first initialize the variable that holds the object that holds the resource to null (here fileWriter), and then include a null check in the cleanup, but that seems unnecessary: if the constructor fails, there's nothing to clean up, so we can just let that exception propagate, which simplifies the code a little.
You could probably do this generically:
static <T extends AutoCloseable, U extends AutoCloseable, V>
T createChainedResource(V v) throws Exception {
// If constructor throws an exception, no resource acquired, so no release required.
U u = new U(v);
try {
return new T(u);
} catch (Exception newTException) {
try {
u.close();
} catch (Exception closeException) {
// Exceptions in cleanup code are secondary to exceptions in primary code (body of try),
// as in try-with-resources.
newTException.addSuppressed(closeException);
}
throw newTException;
}
}
Similarly, you can chain three resources, etc.
As a mathematical aside, you could even chain three times by chaining two resources at a time, and it would be associative, meaning you would get the same object on success (because the constructors are associative), and same exceptions if there were a failure in any of the constructors. Assuming you added an S to the above chain (so you start with a V and end with an S, by applying U, T, and S in turn), you get the same either if you first chain S and T, then U, corresponding to (ST)U, or if you first chained T and U, then S, corresponding to S(TU). However, it would be clearer to just write out an explicit three-fold chain in a single factory function.
Since your resources are nested, your try-with clauses should also be:
try (FileWriter fw=new FileWriter(file)) {
try (BufferedWriter bw=new BufferedWriter(fw)) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
} catch (IOException ex) {
// handle ex
}
I just wanted to build on Jeanne Boyarsky's suggestion of not using ARM but making sure the FileWriter is always closed exactly once. Don't think there are any problems here...
FileWriter fw = null;
BufferedWriter bw = null;
try {
fw = new FileWriter(file);
bw = new BufferedWriter(fw);
bw.write(text);
} finally {
if (bw != null) bw.close();
else if (fw != null) fw.close();
}
I guess since ARM is just syntactic sugar, we can't always use it to replace finally blocks. Just like we can't always use a for-each loop to do something that is possible with iterators.
I would say don't use ARM and go on with Closeable. Use method like,
public void close(Closeable... closeables) {
for (Closeable closeable: closeables) {
try {
closeable.close();
} catch (IOException e) {
// you can't much for this
}
}
}
Also you should consider calling close of BufferedWriter as it is not just delegating the close to FileWriter , but it does some cleanup like flushBuffer.
My solution is to do a "extract method" refactoring, as following:
static AutoCloseable writeFileWriter(FileWriter fw, String txt) throws IOException{
final BufferedWriter bw = new BufferedWriter(fw);
bw.write(txt);
return new AutoCloseable(){
#Override
public void close() throws IOException {
bw.flush();
}
};
}
printToFile can be written either
static void printToFile(String text, File file) {
try (FileWriter fw = new FileWriter(file)) {
AutoCloseable w = writeFileWriter(fw, text);
w.close();
} catch (Exception ex) {
// handle ex
}
}
or
static void printToFile(String text, File file) {
try (FileWriter fw = new FileWriter(file);
AutoCloseable w = writeFileWriter(fw, text)){
} catch (Exception ex) {
// handle ex
}
}
For class lib designers, I will suggest them extend the AutoClosable interface with an additional method to suppress the close. In this case we can then manually control the close behavior.
For language designers, the lesson is that adding a new feature could mean adding a lot others. In this Java case, obviously ARM feature will work better with a resource ownership transfer mechanism.
UPDATE
Originally the code above requires #SuppressWarning since the BufferedWriter inside the function requires close().
As suggested by a comment, if flush() to be called before close the writer, we need to do so before any return (implicit or explicit) statements inside the try block. There is currently no way to ensure the caller doing this I think, so this must be documented for writeFileWriter.
UPDATE AGAIN
The above update makes #SuppressWarning unnecessary since it require the function to return the resource to the caller, so itself does not necessary being closed. Unfortunately, this pull us back to the beginning of the situation: the warning is now moved back to the caller side.
So to properly solve this, we need a customised AutoClosable that whenever it closes, the underline BufferedWriter shall be flush()ed. Actually, this shows us another way to bypass the warning, since the BufferWriter is never closed in either way.
Well, I am trying to write a line of information to log in a text file (.txt) but this is the part where the code fails to write. Everything else works, except this but doesn't give any errors.
public void writeConfig(File config, Boolean append, String errored){
try {
Writer output;
if (config != null){
output = new BufferedWriter(new FileWriter(config));
} else {
output = new BufferedWriter(new FileWriter(er));
}
if (append == true){
output.append(errored);
} else {
output.write(errored);
}
} catch (Exception e){
try {
loadErrorLog(error, true, "Failed to write to Boom's Log.\n");
} catch (Exception e1){
log.info("Major Malfunction #686 : Tell Maker immediatly.");
}
}
}
You're not closing the writer, which means all the data is just staying in the buffer.
You should close it in a finally block.
Additionally:
your use of the append parameter is distinctly dodgy - you should almost certainly be passing it to the constructor of the FileWriter (or FileOutputStream). I don't think append in Writer does what you think it does.
Try to avoid comparing with true - just if (append) would have been clearer
Using the conditional operator could make your FileWriter code cleaner, especially if you used it just for the file:
File file = config == null ? er : config;
Writer writer = new BufferedWriter(new FileWriter(file));
I would avoid using FileWriter in the first place, as it always uses the platform default encoding. Use a FileOutputStream wrapped in an OutputStreamWriter instead, specifying the encoding explicitly (e.g. UTF-8)
Avoid catching Exception in most places; here it would be cleaner to just catch IOException.
It looks like your loadErrorLog method should probably be doing that logging on failure, otherwise I suspect you'll be writing that block of code every time you call it.
Do you really want to continue if you fail to write the config? Is it definitely this method which should handle the exception? I'd potentially remove the catch block entirely (leaving just a try/finally) and let the IOException bubble up the stack
try {
File file = new File("sample.txt");
FileWriter fw = new FileWriter(file,true);
fw.append('d');
fw.write(100);
fw.close();
} catch(IOException exp) {
exp.printStackTrace();
}
I am unable to append or write anything to the file.
But I could read the content from the file.
Is anything wrong with my code?
It sounds like you probably are writing to a file - but not the file you expect to. If no exceptions have been thrown (and swallowing an exception, just writing it to standard out, is rarely the right approach) then the file will exist somewhere.
It will be in whatever directory the code is running from - which may well not be the same as the directory containing the sample.txt file you're reading. I suggest you explore the file system, and also check the Run Configuration in Eclipse to see what the working directory for the app will be.
As an aside, you should be closing the writer in a finally block so that it gets closed even if there's an exception, like this:
File file = new File("sample.txt");
FileWriter fw = null;
try {
fw = new FileWriter(file, true);
fw.append('d');
fw.write(100);
} catch(IOException) {
// Ideally do something to indicate the failure to the caller
// - do you need to catch this at all?
e.printStackTrace();
} finally {
// From Guava
Closeables.closeQuietly(fw);
}
Obviously you can do this without Guava but it'll make things a lot simpler - and not just here. If you're using Java 7 you can make it even simpler with a try-with-resources statement.
http://www.roseindia.net/java/example/java/io/java-write-to-file.shtml
You can Flush context if code is right and still you are facing problem. it "Flushes the stream"
This link can help!
Like was said before the file may be getting cleared out during the build/clean process. Try specificing an absolute path to the file and running it again. Everything you have written is correct sans the corrections already offered.
try {
File file = new File("C:\sample.txt"); // for Windows or possibly just "/sample.txt" for *nix
FileWriter fw = new FileWriter(file,true);
fw.append('d');
fw.write(100);
} catch(IOException e) {
e.printStackTrace();
} finally {
// Good practice to move close to a finally block
fw.close();
}
You may try using the below syntax :
String filename = "C:/sample.txt";
FileWriter fw = new FileWriter(filename,true);
I am creating a file on a network drive and then adding data to it. Time to time writing to that file fails. Is there a good way of checking if the file is accessible before every time i save data to it or maybe is tehre a way checking afther to see if the data was saved?
EDIT:
Right now i am using try-catch block with PrintStream in my code:
try
{
logfile = new File(new File(isic_log), "log_" + production);
//nasty workaround - we'll have a file the moment we assign an output stream to it
if (!logfile.exists())
{
prodrow = production;
}
out = new FileOutputStream(logfile.getPath(), logfile.exists());
p = new PrintStream(out);
if (prodrow != "")
{
p.println (prodrow);
}
p.println (chip_code + ":" + isic_number);
p.close();
}
catch (Exception e)
{
logger.info("Got exception while writing to isic production log: " + e.getMessage());
}
So might be the PrintStream the problem? (PrintWriter and PrintStream never throw IOExceptions)
I would use plain BufferedWriter and add the newlines myself as required.
Normal FileOutputStream operations should throw an IOException if there is an error.
AFAIK, The only exception is PrintWriter which does not throw an exception. Instead you need to call checkError() but it gives you no indication of what the error was or when it occurred.
I suggest you not use PrintWriter in this situation.
The only reasonable way to address this is to try to write to the file, and handle any resulting exception in an appropriate manner. It's pretty much impossible to know beforehand whether an I/O operation is going to succeed, due to the unreliable nature of networks.