I've below code snippet.
Map<String, Object> globalMap = new HashMap<String,Object>();
File talendLogFile = new File("C:\\Softwares\\logFiles\\error.log");
Writer talendLogFileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(talendLogFile, true)));
globalMap.put("Logger", talendLogFileWriter);
((BufferedWriter) globalMap.get("Logger")).write("I'm Writing");
((BufferedWriter) globalMap.get("Logger")).close();
Is there any way I could perform both functionalities happening in last two lines in single line of code? I mean close BufferedWriter just after write.
Besides using try-with-resources, the real answer is: do not do it this way.
You see, you put a writer into a global map. That makes it available to the "whole" world that has access to that map. And next, some code intends to close the writer you added to that map.
But it seems that the writer itself is staying in the map. So other code can notice: the map has a logger/writer ... but how is that other code supposed to know if that logger/writer is still open, or was closed?
Having a logger/writer in that global map, but it can't be used globally, that is a contradiction in itself!
In other words: conceptually, what you are doing seems wrong. Either you add such a logger/writer to a global map, then all code that has access to that map should be able to use that logger/writer (without worrying "is it still open?"). Or, you do not put the logger/writer in such a global map.
Trivially, yes:
((BufferedWriter) globalMap.get("Logger")).write("I'm Writing"); ((BufferedWriter) globalMap.get("Logger")).close();
If you mean use a single method call to do both things, not unless you define a new method to do so.
You can try to use try-catch with resources. That mean resources will be automatically closed after try block will be done. You can read more here https://www.baeldung.com/java-try-with-resources
try(Writer talendLogFileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(talendLogFile, true)))) {
globalMap.put("Logger", talendLogFileWriter);
((BufferedWriter) globalMap.get("Logger")).write("I'm Writing");
}catch(Exception ignored){} //handle the exception if you want
The closest you can get is this, but as already mentiond by many others, there is no need to. It just complicates things:
try (BufferedWriter bw = (BufferedWriter) globalMap.get("Logger")) {
bw.write("I'm Writing");
}
Use try with resources which automatically closes the resource without needing to explicitly close it.
Related
I have a Java program that reads some text from a file, line by line, and writes new text to an output file. But not all the text I write to my BufferedWriter appears in the output file after the program has finished. Why is that?
The details: the program takes a CSV text document and converts it into SQL commands to insert the data into a table. The text file has more than 10000 lines which look similar to following:
2007,10,9,1,1,1006134,19423882
The program seems to work fine except it just stops in the file randomly half way through creating a new SQL statement having printed it into the SQL file. It looks something like:
insert into nyccrash values (2007, 1, 2, 1, 4, 1033092, 259916);
insert into nyccrash values (2007, 1, 1, 1, 1, 1020246, 197687);
insert into nyccrash values (2007, 10, 9, 1
This happens after about 10000 lines but several hundred lines before the end of the file. Where the break happens is between a 1 and a ,. However, the characters doesn't seem important because if I change the 1 to a 42 the last thing written to the new file is 4, which is cutting off the 2 from that integer. So it seems like the reader or writer must just be dying after writing/reading a certain amount.
My Java code is as follows:
import java.io.*;
public class InsertCrashData
{
public static void main (String args[])
{
try
{
//Open the input file.
FileReader istream = new FileReader("nyccrash.txt");
BufferedReader in = new BufferedReader(istream);
//Open the output file.
FileWriter ostream = new FileWriter("nyccrash.sql");
BufferedWriter out = new BufferedWriter(ostream);
String line, sqlstr;
sqlstr = "CREATE TABLE nyccrash (crash_year integer, accident_type integer, collision_type integer, weather_condition integer, light_condition integer, x_coordinate integer, y_coordinate integer);\n\n";
out.write(sqlstr);
while((line = in.readLine())!= null)
{
String[] esa = line.split(",");
sqlstr = "insert into nyccrash values ("+esa[0]+", "+esa[1]+", "+esa[2]+", "+esa[3]+", "+esa[4]+", "+esa[5]+", "+esa[6]+");\n";
out.write(sqlstr);
}
}
catch(Exception e)
{
System.out.println(e);
}
}
}
You need to close your OutputStream which will flush the remainder of your data:
out.close();
The default buffer size for BufferedWriter is 8192 characters, large enough to easily hold hundreds of lines of unwritten data.
You must close() your BufferedWriter. You must close() your BufferedWriter because it IS-A Writer and thus implements AutoCloseable, which means (emphasis added) it is
A resource that must be closed when it is no longer needed.
Some people say you must first call flush() for your BufferedWriter before calling close(). They are wrong. The documentation for BufferedWriter.close() notes that it "Closes the stream, flushing it first" (emphasis added).
The documented semantics of flushing (flush()) are
Flushes this stream by writing any buffered output to the underlying stream
So, you must close, and close will flush any buffered output.
Your output file does not include all the text you wrote to your BufferedWriter because it stored some of that text in a buffer. The BufferedWriter never emptied that buffer, passing it through to the file, because you never told it to do so.
Since Java 7, the best way to ensure an AutoCloseable resource, such as a BufferedWriter, is closed when it is not longer need is to use automatic resource management (ARM), also known as try-with-resources:
try (BufferedWriter out = new BufferedWriter(new FileWriter(file))) {
// writes to out here
} catch (IOException ex) {
// handle ex
}
You must also close your BufferedReader when it is no longer need, so you should have nested try-with-resources blocks:
try (BufferedReader in = new BufferedReader(new FileReader("nyccrash.txt")) {
try (BufferedWriter out = new BufferedWriter(new FileWriter("nyccrash.sql"))) {
// your reading and writing code here
}
} catch (IOException ex) {
// handle ex
}
Do not be tempted (as other answers here suggest) just to call close() at the end of your method, when your code has "finished" using the writer. That will not work if your writing code throws an exception, and in particular if it throws an IOException.
A resource that must be closed when it is no longer needed.
finally {
out.close();//this would resolve the issue
}
Some things to consider:
BufferedWriter.close() flushes the buffer to the underlying stream, so if you forget to flush() and don't close, your file may not have all the text you wrote to it.
BufferedWriter.close() also closes the wrapped Writer. When that's a FileWriter, this will ultimately close a FileOutputStream and tell the OS that you're done writing to the file.
The garbage collector will automatically call close(), not on the BufferedWriter or the wrapped FileWriter, but on the FileOuputStream. So the OS will be happy, but you have to wait for the GC.
However, you always want to release OS resources as soon as you no longer need them. This goes for open files, database connections, print queues ... anything. Trust me on this one.
BufferedWriter.close() does clear up the internal character buffer, so that memory will be available for garbage collection, even while the BufferedWriter itself remains in scope.
So, Always close your resources (not just files) when you're done with them.
If you really want a peek under the covers, most of the Java API's source is available. BufferedWriter is here.
Your code does not appear to be closing the writer after you've finished writing to it. Add an out.close() (preferably in a finally block) and it should work properly.
you dint close your BufferedWriter.close it inside a finally block
finally {
out.close();//this would resolve the issue
}
Always close your resources (not just files) when you're done with them.
finally {
out.close();//this would resolve the issue
}
There might be situations when you want to flush the buffer without closing the file. In these situations you can use the flush-method.
Since you're using BufferedWriter you can also flush the buffer when appropriate:
out.flush()
This will write the rest of the buffer to the actual file. Close-method also flushes the buffer and closes the file.
out.close()
There might be situations when you want to flush the buffer without closing the file. In these situations you can use the flush-method.
You can also use BuffredWriter's newline-method instead of adding \n to the end of the line. Newline-method uses system specific line separator so your code works on different platforms.
out.newLine()
According to documentation it is no use calling flush() method. If you intent to use FileWriter then flush() would help you out.
Basically in this case, you just need to close, BufferedWriter.close() only. This will flush the remainder of your data.
create finally block and put the close method inside so that it will put all data without missing.
finally {
out.close();
}
I want to output my result to a file. I use BufferWriter as below:
public class class1{
...
void print()
{
System.out.println("The name "+outName()+" Tel: "+outNumber());
try{
PrintWriter printWriter=new PrintWriter(new BufferedWriter(new FileWriter("myfile.txt", true)));
printWriter.println("The name "+outName()+" Tel: "+outNumber());
}catch (IOException e){}
}
}
However I have another class and main function also having their own print functions
public class class2{
...
void print()
{
System.out.println("The name "+outName()+" Tel: "+outNumber());
try{
PrintWriter printWriter=new PrintWriter(new BufferedWriter(new FileWriter("myfile.txt", true)));
printWriter.println("The name "+outName()+" Tel: "+outNumber());
}catch (IOException e){}
}
}
public static void main(String[] args) throws IOException{
try{
PrintWriter printWriter=new PrintWriter(new BufferedWriter(new FileWriter("myfile.txt", true)));
...
printWriter.println("something");
printWriter.close();
}catch(IOException e){ }
}
The code pass the compilation, but only the output from the main function appear in the output file. How to fix it please?
There are three (OK ... make that four, no five) significant problems with your code.
In class2 you don't close or flushthePrintWriter` after you have finished writing. That means that the data will never be written out to the file. That's why you never see the output.
This is the obvious bug. But the rest of the problems are also important. Arguably MUCH MORE important ... so keep reading.
The print() method in class2 leaks file descriptors (!). Each time you call it, it will open a file descriptor, write stuff ... and drop it on the floor. If you call print() repeatedly, the FileWriter constructor will fail. You need to close the file, and the cleanest way to ensure it always happens is to write the code like this:
try (PrintWriter printWriter =
new PrintWriter(new BufferedWriter(
new FileWriter("myfile.txt", true)))) {
printWriter.println(...);
}
This is a "try with resource" ... and it guarantees that the resource (printWriter) will be closed when the scope exits.
You are squashing exceptions.
try {
PrintWriter printWriter - ...
} catch (IOException e) {
// SQUASH!!!
}
This is really, really bad. Basically, you have written your code to ignore the exception. Pretend it never happened ... and throw away the information in the exception that would say why it happened.
You should only ever squash an exception if you are absolutely sure that you will only catch expected exceptions, and that ignoring them is absolutely correct. Here, it isn't. If an IOException is thrown here, you need to know why!
Opening multiple streams to write to the same file is a recipe for problems. The streams won't be synchronized, and you are likely to see the output interleaved in the output file in unexpected ways. If the output pipelines include buffering (like yours do), the problem is worse.
You have serious Java style issues:
A class name should always start with an uppercase letter. Always. Even in example code snippets ...
Code should be consistently indented. I recommend using SP characters rather than TAB characters because tabs don't display consistently.
There are style rules about where you should and should not put spaces and line breaks. For example, there should always be whitespace around a binary operator. Find a Java style guide, read it and format your code accordingly.
Always write your code so that >>other people<< can read it.
I think you need to call new class1().print() or new class2().print(), i.e. you need to instantiate the instances first.
Also please remember to close the file in each print() function.
It's because you're never closing anything exept in main(). You're also swallowing exceptions, so you're concealing the truth from yourself. Don't do that.
But it's poor practice. You should keep the file open and use the same FileWriter, BufferedWriter, PrintWriter, and synchronize access to them so you don't get interleaved data.
Not a good idea overall.
I have one scenario where I am trying to implement with the Java 7 'try with resource' feature.
My finally block contains an object of BufferedWriter and File, which I want to close using 'try with resource' feature, instead of closing it by calling close method explicitly.
But I checked on net and saw that the File class does not implement the AutoCloseable interface, but BufferedWriter does. So how can I manage this scenario to implement 'try with resource' feature?
try (BufferedWriter br = new BufferedWriter(new FileWriter(path)))
Use this simply, br will be closed automatically.
Eg. http://www.roseindia.net/java/beginners/java-write-to-file.shtml
You don't need to close a File because it's a pure Java object. It basically just holds the name of the file, nothing else (i.e. it does not require any OS resources to construct).
You only need to close your BufferedWriter and that is correctly AutocCloseable.
You cannot create a BufferedWriter with File only, BufferedWriter requires a Writer, this how it should look like
try (BufferedWriter w = new BufferedWriter(new FileWriter(new File("file")))) {
...
}
try-with-resources will call close only on BufferedWriter. Unfortunately BufferedWriter API does say that it closes the underlying writer, but in fact it does. As for File it has nothing to do with try-with-resources since it is not Autocloseable.
honestly I'm not very experienced with exception handling, because often for my laziness I tend to not handle exceptions. So here's a very basic question.
I would like to know what's the cleanest way to accomplish this situation, with an exception handling approach:
I have a class (ConfigManager) that reads a file within its constructor, and need that file to exists to be constructed correctly, given as the constructor parameter.
If the file doesn't exist, I would like to catch the FileNotFoundException, create the file with some defaults values, and continue the creation of the ConfigManager object with the default config file now available.
Here's some code:
class ConfigManager{
ConfigManager(String file){
try{
builder = builderFactory.newDocumentBuilder();
document = builder.parse (new FileInputStream(file));
....
}catch (FileNotFoundException e) {
File configFile = new File (file);
try {
configFile.createNewFile();
BufferedWriter writer = new BufferedWriter(new FileWriter(configFile));
writer.write(this.defaultConfig);
writer.close();
return new ConfigManager(string); //Here's the problem. I can't do that but I need to try build ConfigManager again. How do that?
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
How to construct a new ConfigManager object, after the default config file has been created?
Is that the rigth way to handle such type of exception?
thanks in advance
What you can do is ensure the file exists before attempting to parse it.
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
BufferedWriter writer = new BufferedWriter(new FileWriter(configFile));
writer.write(defaultConfig);
writer.close();
fis = new FileInputStream(file);
}
try{
builder = builderFactory.newDocumentBuilder();
document = builder.parse (fis);
don't do the reading file in the constructor, create a method (possibly private) that does the reading of the file and setting of the values on the ConfigManager.
Then in the constructor, where you try to call the constructor again, just call the method.
i.e. dont call the constructor again.
update -- I would organize the code like this:
ConfigManager(String fileName) {
File file = new File(fileName);
if (!file.exists()){
// create this method -- Im assuming its ok to put the default
// config on the path where the file did not exist.
createDefaultConfigFile(fileName);
}
parseConfigFile(fileName, ...); // create this method too
}
this is obviously not working code, and I dont know specifically what you are doing so its as far as I can go. But its more readable than what you have now, and a bit more organized. Also, do you really want to create a new default config file if the specified one does not exist? Why not pop up a warning saying the config did not exist so you are using defaults, but not write the default file? You might have a reason to write the default, and if thats true then ok, but if you don't have to, don't add more work...
The solution is to partition your constructor into two parts. The first part tries to create the FileInputStream from the existing file. If it throws the FileNotFoundException, then you create and populate the file as above, and then open the FileInputStream again. The second part takes the file FileInputStream opened by the first part (regardless of how it was opened) and proceeds with initialization.
Another option is to defer this loading to an init() method, so that consumers of your class must both create and initialize their objects.
You need to be able to call the constructor again, but without creating a new object - just calling it on the same object. Since Java doesn't allow you to do that, you have to create an auxillary method, move the code from the constructor into that, and then call the new method from the constructor.
This is a basic technique for any situation where you need to implement recursion, but you can't directly recurse.
The cleanest way of accomplishing this is not to perform any operations that can result in exceptions in the constructor. If you absolutely need to perform them before your object can be used, do them in a separate method init().
Try delegating the parsing of the configuration file to another method. That way, you can check if the file exists first and then either create a default one, or pass the existing one to this new method.
Well, actually you have a new instance of ConfigManager after the constructor was executed without an error. So all you have to to is to just remove the line in question.
Or consider using a static initializer. This will check for the file only once, when your application is deployed/started.
often for my laziness I tend to not
handle exceptions
I suggest you fix the laziness first. In reality you are just creating more work for yourself further down the line.
hey people,
I have a text file which I need to append in my app. Now I could rewrite the entire file incorporating the changes to a specific line but I'm hoping there is a more efficient solution.
I know the line number I need to append however I'm unsure how to get to that line, preferably without looping through all of the others unless that is the only way. This is what I have so far which recreates the entire file:`
try {
FileOutputStream fOut = openFileOutput("tasklist.txt", MODE_APPEND);
BufferedOutputStream buf = new BufferedOutputStream(fOut);
OutputStreamWriter osw = new OutputStreamWriter(buf);
BufferedWriter writer = new BufferedWriter(osw);
for(int count = 0; count < str.size(); count++)
{
writer.write(str[count]);
writer.write("\r\n");
}
writer.flush();
writer.close();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "Error saving txt file", Toast.LENGTH_SHORT);
}`
Hopefully someone knows of a more efficient solution. Thanks.
There are some cleaner ways, but with file handling there isn't really a more efficient way (that I know of). You basically go from start to finish, as you have done, and append data. That's how file I/O works (it's not an Android or Java thing).
Still, you could try FileWriter to tidy it up a bit (the "true" param to the ctor means append):
FileWriter writer = new FileWriter(aFile, true));
try {
writer.write("append here\n");
} finally {
writer.close();
}
Be advised though, FileWriter uses the systems default encoding. This should be fine on Android, but be careful with it in general.
Here are some good general practices for dealing with reading and writing files with Java.
Also, depending on what you're doing with this file you're appending to (how often you are editing the same file, and from what processes), you may need to make a copy of it, and or deal with fysnc, to make sure you don't lose data on Android devices that use journaling filesystems.
To make your app more efficient though, maybe you could cache data in memory, and only write out the entire file (rather than append), at certain intervals, or when you're done. If you have a lot of data, a DB might even be appropriate.