I wrote a method that prepares SQL insert statements and stores them in a text file. At this point it gets the job done, but I have a catch block that is a total eyesore. If I could somehow close a BufferedReader without implicitly calling flush that would be perfect. Is that possible? If yes, how?
As preparation for populating a master table with data on kanji(Japanese characters) for the memorization application I am making, I am making a list of all the characters. The data source is KANJIDIC2, a UTF-8 encoded xml file with data on 13k+ characters. The original idea was to include all the characters in the source file, but for some reason 300-or-so characters throw a java.nio.charset.MalformedInputException when I try to write them to my output file.
I decided to give up on those characters since they're not essential or anything, but I couldn't find a smooth way to close my BufferedReader after the exception above.
File outputFile = new File("C:\\Users\\tobbelobb\\Documents\\kanjilist.bsv");
try {
BufferedWriter bw = Files.newBufferedWriter(outputFile.toPath(), StandardCharsets.UTF_8);
for (Kanji nextKanji : kanjiList) {
try {
StringBuilder sb = new StringBuilder();
// sb.append stuff from list of objects...
bw.write(sb.toString());
bw.newLine();
bw.flush();
} catch (MalformedInputException ex) {
// Ungracefully swallow the exception.
ex.printStackTrace();
bw = Files.newBufferedWriter(outputFile.toPath(), StandardCharsets.UTF_8, StandardOpenOption.APPEND);
}
}
bw.close();
} catch (Exception ex) {
ex.printStackTrace();
}
I looked for a method to dispose of my BufferedReader object in the catch block, but the only one I could find is close(), which throws that same MalformedInputException again, and in the process writes an incomplete line of text to my file.
There is no such thing: https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/io/BufferedWriter.java#L258
public void close() throws IOException {
synchronized (lock) {
if (out == null) {
return;
}
try {
flushBuffer();
} finally {
out.close();
out = null;
cb = null;
}
}
}
so it always tries to flush, and that is probably what most users expect anyway.
What you can do is to generate your lines separately, using an in-memory BufferedWriter. If it dies, you skip the line, if it works, you write it. Also, it is 2019 now, so please start using try-with-resources.
try(BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(outputFile))) {
for (Kanji nextKanji : kanjiList) {
try {
StringBuilder sb = new StringBuilder();
// sb.append stuff from list of objects...
ByteArrayOutputStream baos=new ByteArrayOutputStream();
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(baos));
bw.write(sb.toString());
bw.newLine();
bw.close();
baos.writeTo(bos);
} catch (MalformedInputException ex) {}
}
}
if it works at all (I am just writing from the top of my head), it can be prettier with a single ByteArrayOutputStream instance, and use its reset() in the loop.
Related
Unable to delete files even after closing the corresponding readers and writers.
Permissions are present on the files
file.delete() returns false
my code
main(){
try{
File file=new File(path);// Path where the file is present
FileReader reader = new FileReader(path);
BufferedReader br = new BufferedReader(reader);
FileWriter writer = new FileWriter(pathOther);
BufferedWriter wr = new BufferedWriter(writer);
// Readers and writers for i/o operations
while((String str=br.readLine())!=null){
wr.write(str); // Copying to another file
}
}catch(Exception e){}
finally{
reader.close(); //close reader
writer.close(); //close writer
file.delete(); //This returns false
}
My guess as to what is going on is that you close the FileInputStream but leave the BufferedReader open, which leaves something holding on to the file handle. Then, when you try to delete the file, it returns false because something else has a handle on it.
Try the following code:
File file = new File(path);
try {
br = new BufferedReader(new FileReader(file));
// use the reader ...
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
// now close the file
file.delete();
Update:
While testing the above code I noticed something else which could also cause the observations you were seeing. If the file at path does not exist, then logically calling file.delete will also fail for this reason. So you should make sure that the file actually exists before trying to delete it. You can call file.exists() to check for this.
First, you should close the BufferedReader instead of the FileReader (the BufferedReader will in turn call close() on the FileReader):
So instead of:
reader.close(); //close reader
do:
br.close();
(and leave out the complete redundant comment).
Also, since File.delete() simply returns a Boolean and doesn't tell you why it failed, you can get more information by calling Files.delete instead:
try {
Files.delete(file.toPath());
} catch (IOException e) {
// e now contains information about why it can't delete.
}
Nothing will work call System.gc();
I'm creating a mini program that deletes Files using the File.delete() method but I'm having a little bit of an issue if I use the buffered Reader to read the .txt file before I delete it, it doesn't delete the file. I did come up with a solution for it: I just close the buffered reader before I delete the file. however this doesn't make sense to me as to why this is happening can anyone explain this.
import java.io.*;
import java.nio.file.Files;
public class Purge {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String sample;
boolean result = false;
BufferedReader amg = new BufferedReader(new FileReader("C:/Users/Steven/Desktop/me.txt"));
sample = amg.readLine();
amg.close();// closes the buffered reader
System.out.println("Haha I'm stille here: "+sample);
File anesu = new File("C:/Users/Steven/Desktop/me.txt");
if (anesu.exists()){
try{result = anesu.delete();
}catch( Exception x){
System.out.println("Problem Deleting File"+x);
}
catch( Throwable e){
System.out.println("Problem Deleting File Throwable"+e);
}
}else{
System.out.println("No File ");
}
System.out.println("File has been deleted: "+result);
}
}
When a stream object is garbage collected, its finalizer closes the underlying file descriptor. So, the fact that the delete only works when you added the System.gc() call is strong evidence that your code is somehow failing to close some stream for the file. It may well be a different stream object to the one that is opened in the code that you posted.
Note :
Properly written stream handling code uses a finally block to make sure that streams get closed no matter what.
If you does not want to use System.gc(), read your content with FileInputStream
InputStream in = new FileInputStream(new File("C:/temp/test.txt"));
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder out = new StringBuilder();
try {
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
}
System.out.println(out.toString()); //Prints the string content read from input stream
}
catch(Exception ex) {//TODO}
finally {
reader.close();
}
You can delete the file in the finally block.
A downside to this approach is that if an exception is thrown the file will still be deleted.
public Stream<String> readLines(Path archive) {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
(new FileInputStream(archive.toFile()))));
return bufferedReader.lines();
} catch (IOException e) {
throw new UncheckedIOException(e);
} finally {
try {
Files.delete(archive);
System.out.println("Deleted: " + archive);
} catch (IOException e) {
System.out.println("Unable to delete: " + archive);
}
}
}
I am using BufferedWriter to write text into a notepad.txt file. The program writes the text with a new line for every sentence, but when I increase the size of notepad, all the lines connect to each other. How do I stop that from happening?
bw.write(Text);
bw.close();
Because after the lines connect to each other, the program cant read from the file any more, because the line structure is different and doesn't recognize it.
Use bw.newLine() to insert a new line character, so that it will not connect
How about the PrintWriter class in java?
It will be one of better option for the situation.
The usage of the class looks as follows,
public void writeFile() {
String someText = "some of my text";
PrintWriter out = null;
try {
out = new PrintWriter(
new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("myout.out")))));
out.println(someText);
out.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
if(out != null) out.close();
}
}
Too lat answer,
Regards,
I've come across a problem using FileOutputStream and BufferedWriter in Java.
If my disk space is full and I'm trying to write, it will throw IOException (which is correct), but when calling the writer.close(), it will fail to close the resource, throwing another IOException and keeping the resource opened!
Here is my workaround with writer.flush(). It seems to work, but is there a better way to handle this?
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), encoding));
StringBuilder buff = new StringBuilder();
writeToStream(buff, separator, data);
writer.write(buff.toString());
writer.flush(); // flush before closing to make sure there is enough space on disk to complete the close()
logger.trace("writeFile: file written, file={}", file);
} catch (IOException e) {
logger.error("writeFile: cannot write to file: {}", file, e);
throw new ... //some exception wrapper here
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
// ignore
}
}
}
You should try and close all resources in the reverse order in which you have opened them. Here you try and close only one.
If you have Java 7, use the try-with-resources statement. If you don't, the best way to do that is using Guava's Closer (available since version 14.0):
final Closer closer = Closer.create();
final FileOutputStream out;
final OutputStreamWriter writer;
final BufferedWriter buffered;
try {
out = closer.register(new FileOutputStream(file), encoding));
writer = closer.register(new OutputStreamWriter(out));
buffered = closer.register(new BufferedWriter(writer));
// do stuff
} catch (IOException e) {
throw closer.rethrow(e);
} finally {
closer.close();
}
If you don't have Closer, it is easy enough to recreate.
Is there a way to check whether a file was correctly written, I mean if there is an EOF at the end?
I'm asking that because I have a program that takes some file, merge them in a very big file and then use it to get statistics from it.
The point is that the second part never ends because it doesn't recognize the end of file.
The relevant parts of the code are the following:
(please do not ask for the whole code as I cannot post for important reasons)
FileWriter file=null;
PrintWriter pw = null;
String pathToRead=null;
InputStreamReader isr = null;
BufferedReader br = null ;
FileInputStream fis = null ;
TestJFileChooser d=new TestJFileChooser();
int c=1;
String line=null;
....
//here i select the files
selectedFile=new File(pathToRead);
//here I get one buffer reader for each file got with listFiles()
for(File file_sel:app){
if (file_sel.getName().startsWith("gtou")){
System.out.println(file_sel.getName());
fis = null;
try {
fis = new FileInputStream(file_sel);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
isr=new InputStreamReader(fis);
br=new BufferedReader(isr);
map.put(i, br);
num_file++;
i++;
}
}
//then I select the output file and open a print writer for it
fileToWrite=new File(pathToRead);
try {
file = new FileWriter(fileToWrite);
pw= new PrintWriter(file);
} catch (IOException e1) {
e1.printStackTrace();
}
//merging part
....
line=br.readLine();
while(line!=null){
System.out.println("line is:"+line);
....
line=br.readLine();
}
//end of merging ....
pw.flush();
pw.close();
try {
if (file!=null) file.close();
fis.close();
isr.close();
br.close();
for(int fi=0;fi<num_file;fi++){
br2=map.get(fi);
br2.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
so.kill();
Runtime r=Runtime.getRuntime();
r.gc();
//this is a popup that comes out
GlitchSquad gli=new GlitchSquad("Completed");
the problem is that as output I get:
line is: null ;
line is: null ;
line is: null ;
etc
And never get to "completed" popup =(
I cannot understand what is exactly that null because the control line!=null doesn't work.
I also tried to use that null as a string ..but nothing..
I thought that was a problem in how I close the streams but now the code seems correct to me ..but still no way to stop it..
Suggestion?
Thanks in advance!
p.s. it is a summarized version in order to focus on the streams.. variables are correctly declared and the same is for imports etc
edit: code updated
EOF is EOF. There is no more data. Unless you have an expected EOF mark within the file, or a self-describing protocol that tells you where the EOF mark should be, there is no way to determine whether the file was completely written.
I don't know if it will solve your problem, but I'd be using this code instead:
try {
fis = new FileInputStream(file_sel);
isr=new InputStreamReader(fis);
br=new BufferedReader(isr);
map.put(num_file++, br);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Otherwise there may be uncaught "NullPointer"-exceptions or strange BufferedReaders in your "map". ( I don't right now know how new InputStreamReader(null) will behave.)
It looks like i and num_file have always equal values, so just drop i. Or use a LinkedList and drop both.
If there's not a special merging that you have to do, I'd just do it like this:
OutputStream os;
try {
os = new FileOuputStream(outfile);
} catch (FileNotFoundException e) {
os = null;
e.printStackTrace();
}
if (os != null) {
for(File file_sel:app) {
if (file_sel.getName().startsWith("gtou")) {
System.out.println(file_sel.getName());
InputStream is = null;
try {
is = new FileInputStream(file_sel);
byte[] buffer = new byte[1024];
int readBytes = 0;
while ((readBytes = is.read(buffer)) > 0) {
os.write(buffer, 0, readBytes);
}
fos.flush();
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
If you read files with different encodings, you will have to modify at least the reading of course.
If it doesn't work, I'd suggest you build a "summarized" and runable sample program.
The core of your question is this code:
BufferedReader br = ...
String line = br.readLine();
while (line != null) {
System.out.println("line is:" + line);
...
line = br.readLine();
}
You say that this repeatedly outputs this:
line is: null ;
line is: null ;
(Notice the " ;" on the end!!!)
The only way that can happen is if the file you are reading contains at least one line that look like this:
null ;
Indeed, unless the "..." code includes a continue statement, there must must be lots of those lines in the input file.
Is there a way to check whether a file was correctly written?
Yea. Look at it using a text editor and/or check its file size.
I mean if there is an EOF at the end?
In modern file systems, EOF is a position not a marker. Specifically it is the position after the last byte of the file. So it is logically impossible for a file to not have an EOF. (You'd have to have a file that is infinite in length for there to be no EOF.)