Writing from Stream<String> to PrintWriter drops lines [duplicate] - java

For some reason my String is written partially by PrintWriter. As a result I am getting partial text in my file. Here's the method:
public void new_file_with_text(String text, String fname) {
File f = null;
try {
f = new File(fname);
f.createNewFile();
System.out.println(text);
PrintWriter out = new PrintWriter(f, "UTF-8");
out.print(text);
} catch (IOException e) {
e.printStackTrace();
}
}
Where I print text to a console, I can see that the data is all there, nothing is lost, but apparently part of text is lost when PrintWriter does its job... I am clueless..

You should always Writer#close your streams before you discard your opened streams. This will free some rather expensive system resources that your JVM must quire when opening a file on the file system. If you do not want to close your stream, you can use Writer#flush. This will make your changes visible on the file system without closing the stream. When closing the stream, all data is flushed implicitly.
Streams always buffer data in order to only write to the file system when there is enough data to be written. The stream flushes its data automatically every now and then when it in some way considers the data worth writing. Writing to the file system is an expensive operation (it costs time and system resources) and should therefore only be done if it really is necessary. Therefore, you need to flush your stream's cache manually, if you desire an immediate write.
In general, make sure that you always close streams since they use quite some system resources. Java has some mechanisms for closing streams on garbage collection but these mechanisms should only be seen as a last resort since streams can live for quite some time before they are actually garbage collected. Therefore, always use try {} finally {} to assure that streams get closed, even on exceptions after the opening of a stream. If you do not pay attention to this, you will end up with an IOException signaling that you have opened too many files.
You want to change your code like this:
public void new_file_with_text(String text, String fname) {
File f = null;
try {
f = new File(fname);
f.createNewFile();
System.out.println(text);
PrintWriter out = new PrintWriter(f, "UTF-8");
try {
out.print(text);
} finally {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}

Try to use out.flush(); right after the line out.print(text);
Here is a proper way to write in a file :
public void new_file_with_text(String text, String fname) {
try (FileWriter f = new FileWriter(fname)) {
f.write(text);
f.flush();
} catch (IOException e) {
e.printStackTrace();
}
}

I tested you code. You forgot to close the PrintWriter object i.e out.close
try {
f = new File(fname);
f.createNewFile();
System.out.println(text);
PrintWriter out = new PrintWriter(f, "UTF-8");
out.print(text);
out.close(); // <--------------
} catch (IOException e) {
System.out.println(e);
}

You must always close your streams (which will also flush them), in a finally block, or using the Java 7 try-with-resources facility:
PrintWriter out = null;
try {
...
}
finally {
if (out != null) {
out.close();
}
}
or
try (PrintWriter out = new PrintWriter(...)) {
...
}
If you don't close your streams, not only won't everything be flushed to the file, but at some time, your OS will be out of available file descriptors.

You should close your file:
PrintWriter out = new PrintWriter(f, "UTF-8");
try
{
out.print(text);
}
finally
{
try
{
out.close();
}
catch(Throwable t)
{
t.printStackTrace();
}
}

Related

Close multiple resources with AutoCloseable (try-with-resources)

I know that the resource you pass with a try, will be closed automatically if the resource has AutoCloseable implemented. So far so good. But what do I do when i have several resources that I want automatically closed. Example with sockets;
try (Socket socket = new Socket()) {
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
}
So I know the socket will be closed properly, because it's passed as a parameter in the try, but how should the input and output be closed properly?
Try with resources can be used with multiple resources by declaring them all in the parenthesis. See the documentation
Relevant code excerpt from the linked documentation:
public static void writeToFileZipFileContents(String zipFileName,
String outputFileName)
throws java.io.IOException {
java.nio.charset.Charset charset =
java.nio.charset.StandardCharsets.US_ASCII;
java.nio.file.Path outputFilePath =
java.nio.file.Paths.get(outputFileName);
// Open zip file and create output file with
// try-with-resources statement
try (
java.util.zip.ZipFile zf =
new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer =
java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
// Enumerate each entry
for (java.util.Enumeration entries =
zf.entries(); entries.hasMoreElements();) {
// Get the entry name and write it to the output file
String newLine = System.getProperty("line.separator");
String zipEntryName =
((java.util.zip.ZipEntry)entries.nextElement()).getName()
newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
}
If your objects don't implement AutoClosable (DataInputStream does), or must be declared before the try-with-resources, then the appropriate place to close them is in a finally block, also mentioned in the linked documentation.
Don't worry, things will "just work". From Socket's documentation:
Closing this socket will also close the socket's InputStream and OutputStream.
I understand your concern about not explicitly calling close() on the input and output objects and in fact it's generally better to ensure all resources are automatically managed by the try-with-resources block, like this:
try (Socket socket = new Socket();
InputStream input = new DataInputStream(socket.getInputStream());
OutputStream output = new DataOutputStream(socket.getOutputStream());) {
} catch (IOException e) {
}
This would have the effect that the socket object would be "closed multiple times", but that should not do any harm (this is one of the reasons why it's generally advised that all implementations of close() be made idempotent).
In addition to the above answers, This is the improvement added in Java 9.
Java 9 try-with-resources makes an improved way of writing code. Now you can declare the variable outside the try block and use them inside try block directly.because of this you will get following benefits.
The Resources which it declared outside try( which is effectively final or final) can be automatically close by automatic resource management by just adding them in the try block.
You no need to re-refer objects declared outside try block nor need to close them manually as we need to do in Java 7.
It also helps to write clean code.
try-with-resource can we write like this in Java 9.
public void loadDataFromDB() throws SQLException {
Connection dbCon = DriverManager.getConnection("url", "user", "password");
try (dbCon; ResultSet rs = dbCon.createStatement().executeQuery("select * from emp")) {
while (rs.next()) {
System.out.println("In loadDataFromDB() =====>>>>>>>>>>>> " + rs.getString(1));
}
} catch (SQLException e) {
System.out.println("Exception occurs while reading the data from DB ->" + e.getMessage());
}
}
Here automatic resource management will automatically close both the objects dbCon & rs.
For the better understanding of the list of above define use cases please find some Java 7 code.
Example 1:
public void loadDataFromDB() throws SQLException {
Connection dbCon = DriverManager.getConnection("url", "user", "password");
try (ResultSet rs = dbCon.createStatement().executeQuery("select * from emp")) {
while (rs.next()) {
System.out.println("In loadDataFromDB() =====>>>>>>>>>>>> " + rs.getString(1));
}
} catch (SQLException e) {
System.out.println("Exception occurs while reading the data from DB ->" + e.getMessage());
} finally {
if (null != dbCon)
dbCon.close();
}
}
Example 2:
// BufferedReader is declared outside try() block
BufferedReader br = new BufferedReader(new FileReader("C://readfile/input.txt"));
try (BufferedReader inBr = br) {
// ...
}
} catch (IOException e) {
// ...
}
In the above samples you can see if the object is ouside try then either we need to close manually or re-refer it. Also in the case of multiple objects in the try block, it looks messy and even if you declared inside try then you can't use outside try block.
Answers above are great but there are some cases when try-with-resources doesn't help.
Take a look at this code example:
private static byte[] getFileBytes(Collection<String> fileContent) throws CustomServiceException {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(baos))) {
for (String fileLine : fileContent) {
writer.append(fileLine);
writer.newLine();
}
}
return baos.toByteArray();
} catch (IOException e) {
throw new CustomServiceException(SC_INTERNAL_SERVER_ERROR, "Unable to serialize file data.");
}
}
In this example u can't just use try-with-resources block cause writer has to flush the output buffer to the underlying character stream so placing writer into try-with-resources block won't do the trick and method will return empty array.

How to close file in Java and/or know where in my code some file is locked?

Apparently I am always calling FileReader#close() and FileWriter#close(), but some of my files remained locked by my own code.
How to
1) close file fully?
2) check, where in the code it was opened and not closed?
The question is vague and is missing context, so it makes it difficult to answer and encourages assumptions, never a good place to start from...
However, if you are doing something similar to...
try {
FileReader fr = new FileReader(new File("..."));
// Read file...
fr.close();
} catch (IOException exp) {
exp.printStackTrace();
}
Then if an exception occurs for some reason (or the code returns before it reaches the close statement), then close will never be called...
Prior to Java 7, one would typically do something like...
FileReader fr = nulll;
try {
fr = new FileReader(new File("..."));
// Read file...
} catch (IOException exp) {
exp.printStackTrace();
} finally {
try {
// Avoid NullPointerException's
if (fr != null) {
fr.close();
}
} catch (Exception exp) {
}
}
This ensures that regardless of what happens between the try-catch, finally will always be called and you can take steps to ensure that the resource is closed.
With Java 7, you can now take advantage of the "try-with-resources" feature...
try (FileReader fr = new FileReader(new File("..."))) {
fr = ;
// Read file...
} catch (IOException exp) {
exp.printStackTrace();
}
Which is basically a short-cutted version of the try-catch-finally example block.
If you are using the FileLock functionality, then you also need to ensure that you releasing the FileLock when you are done with, in a similar fashion to the try-catch-finally example above, but file locking will only ensure that different processes can't read/write the simultaneously, it doesn't protect you against multiple threaded access...

Writing to Text File [duplicate]

This question already has answers here:
BufferedWriter not writing everything to its output file
(8 answers)
Closed 8 years ago.
So I'm using this function to write to text file, but the text file always ends up empty after executing. Can anyone see what the error might be? I've been stuck on this for a while.
public static void writeTextFile(String fileName, String s) {
FileWriter output = null;
try {
output = new FileWriter(fileName);
BufferedWriter writer = new BufferedWriter(output);
writer.write(s);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
// Ignore issues during closing
}
}
}
}
Just change your to include writer.close(); as given below
try {
output = new FileWriter(fileName);
BufferedWriter writer = new BufferedWriter(output);
writer.write(s);
writer.close();
}
//remaining code
The reason your data not saved in the file because , The Data is saved only if you call writer.flush(); And calling the writer.flush() method is enough to just save data. But you need to close the BufferedWriter() like writer.close(); to avoid resource leak. The close() calls flush() method for you before closing the stream.
After writing your output you should make sure to flush and close the socket, specially because you are using a buffered output.
writer.write(s);
writer.flush();
writer.close();
If you don't do that, the BufferedWriter will wait for additional data, but there does come none and the program execution is stopped suddenly. Using flush here is optional, as when closing it the flush is implicit, but personally I call it everytime I need to be sure that something goes out. Just like when on the toilet ;)
When you use a Buffer to write something, you must close him when you re end
writer.close();
Without closing bufferwriter you cannot see output on text file
try to add this code
writer.close()

Not writing to text file

I currently am having problems writing to the text file in my code, the entirety of the program is hit and everything will print out to the console. no errors. But the file is empty. Any suggestions?
public textFiles(String filePath)
{
File file = new File(filePath);
try{
fstream = new FileWriter(filePath,true);
}
catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
out = new BufferedWriter(fstream);
System.out.println("try");
addToText("WOOOOHOOO");
System.out.println(file.exists());
}
public void addToText(String Line)
{
try {
out.write(Line);
out.newLine();
} catch (IOException e) {
System.err.println("writing Error");
}
System.out.println("SHOULDA F****** WORKED");
}
You're never closing the stream, and so probably never flushing the stream either - the text essentially gets cached when you print it out, and gets flushed to the file in chunks (usually chunks that are much bigger than what you're writing, hence the lack of output.)
Make sure you close the stream when you're done (fstream.close();), and it should work fine (the stream will automatically flush to clear any output when it's closed).
Try this code to write a .txt file in any drive.
try
{
String ss="html file write in java";
File file= new File("F:\\inputfile\\aa.txt");
FileWriter fwhn= new FileWriter(file);
fwhn.write(ss);
fwhn.flush();
}
catch(Exception ex)
{
}

file.delete() returns false even though file.exists(), file.canRead(), file.canWrite(), file.canExecute() all return true

I'm trying to delete a file, after writing something in it, with FileOutputStream. This is the code I use for writing:
private void writeContent(File file, String fileContent) {
FileOutputStream to;
try {
to = new FileOutputStream(file);
to.write(fileContent.getBytes());
to.flush();
to.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
As it is seen, I flush and close the stream, but when I try to delete, file.delete() returns false.
I checked before deletion to see if the file exists, and: file.exists(), file.canRead(), file.canWrite(), file.canExecute() all return true. Just after calling these methods I try file.delete() and returns false.
Is there anything I've done wrong?
Another bug in Java. I seldom find them, only my second in my 10 year career. This is my solution, as others have mentioned. I have nether used System.gc(). But here, in my case, it is absolutely crucial. Weird? YES!
finally
{
try
{
in.close();
in = null;
out.flush();
out.close();
out = null;
System.gc();
}
catch (IOException e)
{
logger.error(e.getMessage());
e.printStackTrace();
}
}
It was pretty odd the trick that worked. The thing is when I have previously read the content of the file, I used BufferedReader. After reading, I closed the buffer.
Meanwhile I switched and now I'm reading the content using FileInputStream. Also after finishing reading I close the stream. And now it's working.
The problem is I don't have the explanation for this.
I don't know BufferedReader and FileOutputStream to be incompatible.
I tried this simple thing and it seems to be working.
file.setWritable(true);
file.delete();
It works for me.
If this does not work try to run your Java application with sudo if on linux and as administrator when on windows. Just to make sure Java has rights to change the file properties.
Before trying to delete/rename any file, you must ensure that all the readers or writers (for ex: BufferedReader/InputStreamReader/BufferedWriter) are properly closed.
When you try to read/write your data from/to a file, the file is held by the process and not released until the program execution completes. If you want to perform the delete/rename operations before the program ends, then you must use the close() method that comes with the java.io.* classes.
As Jon Skeet commented, you should close your file in the finally {...} block, to ensure that it's always closed. And, instead of swallowing the exceptions with the e.printStackTrace, simply don't catch and add the exception to the method signature. If you can't for any reason, at least do this:
catch(IOException ex) {
throw new RuntimeException("Error processing file XYZ", ex);
}
Now, question number #2:
What if you do this:
...
to.close();
System.out.println("Please delete the file and press <enter> afterwards!");
System.in.read();
...
Would you be able to delete the file?
Also, files are flushed when they're closed. I use IOUtils.closeQuietly(...), so I use the flush method to ensure that the contents of the file are there before I try to close it (IOUtils.closeQuietly doesn't throw exceptions). Something like this:
...
try {
...
to.flush();
} catch(IOException ex) {
throw new CannotProcessFileException("whatever", ex);
} finally {
IOUtils.closeQuietly(to);
}
So I know that the contents of the file are in there. As it usually matters to me that the contents of the file are written and not if the file could be closed or not, it really doesn't matter if the file was closed or not. In your case, as it matters, I would recommend closing the file yourself and treating any exceptions according.
There is no reason you should not be able to delete this file. I would look to see who has a hold on this file. In unix/linux, you can use the lsof utility to check which process has a lock on the file. In windows, you can use process explorer.
for lsof, it's as simple as saying:
lsof /path/and/name/of/the/file
for process explorer you can use the find menu and enter the file name to show you the handle which will point you to the process locking the file.
here is some code that does what I think you need to do:
FileOutputStream to;
try {
String file = "/tmp/will_delete.txt";
to = new FileOutputStream(file );
to.write(new String("blah blah").getBytes());
to.flush();
to.close();
File f = new File(file);
System.out.print(f.delete());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
It works fine on OS X. I haven't tested it on windows but I suspect it should work on Windows too. I will also admit seeing some unexpected behavior on Windows w.r.t. file handling.
If you are working in Eclipse IDE, that could mean that you haven't close the file in the previous launch of the application. When I had the same error message at trying to delete a file, that was the reason. It seems, Eclipse IDE doesn't close all files after termination of an application.
Hopefully this will help. I came across similar problem where i couldn't delete my file after my java code made a copy of the content to the other folder. After extensive googling, i explicitly declared every single file operation related variables and called the close() method of each file operation object, and set them to NULL. Then, there is a function called System.gc(), which will clear up the file i/o mapping (i'm not sure, i just tell what is given on the web sites).
Here is my example code:
public void start() {
File f = new File(this.archivePath + "\\" + this.currentFile.getName());
this.Copy(this.currentFile, f);
if(!this.currentFile.canWrite()){
System.out.println("Write protected file " +
this.currentFile.getAbsolutePath());
return;
}
boolean ok = this.currentFile.delete();
if(ok == false){
System.out.println("Failed to remove " + this.currentFile.getAbsolutePath());
return;
}
}
private void Copy(File source, File dest) throws IOException {
FileInputStream fin;
FileOutputStream fout;
FileChannel cin = null, cout = null;
try {
fin = new FileInputStream(source);
cin = fin.getChannel();
fout = new FileOutputStream(dest);
cout = fout.getChannel();
long size = cin.size();
MappedByteBuffer buf = cin.map(FileChannel.MapMode.READ_ONLY, 0, size);
cout.write(buf);
buf.clear();
buf = null;
cin.close();
cin = null;
fin.close();
fin = null;
cout.close();
cout = null;
fout.close();
fout = null;
System.gc();
} catch (Exception e){
this.message = e.getMessage();
e.printStackTrace();
}
}
the answer is when you load the file, you need apply the "close" method, in any line of code, works to me
There was a problem once in ruby where files in windows needed an "fsync" to actually be able to turn around and re-read the file after writing it and closing it. Maybe this is a similar manifestation (and if so, I think a windows bug, really).
None of the solutions listed here worked in my situation. My solution was to use a while loop, attempting to delete the file, with a 5 second (configurable) limit for safety.
File f = new File("/path/to/file");
int limit = 20; //Only try for 5 seconds, for safety
while(!f.delete() && limit > 0){
synchronized(this){
try {
this.wait(250); //Wait for 250 milliseconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
limit--;
}
Using the above loop worked without having to do any manual garbage collecting or setting the stream to null, etc.
The problem could be that the file is still seen as opened and locked by a program; or maybe it is a component from your program that it had been opened in, so you have to ensure you use the dispose() method to solve that problem.
i.e. JFrame frame;
....
frame.dispose();
You have to close all of the streams or use try-with-resource block
static public String head(File file) throws FileNotFoundException, UnsupportedEncodingException, IOException
{
final String readLine;
try (FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
LineNumberReader lnr = new LineNumberReader(isr))
{
readLine = lnr.readLine();
}
return readLine;
}
if file.delete() is sending false then in most of the cases your Bufferedreader handle will not be closed. Just close and it seems to work for me normally.
I had the same problem on Windows. I used to read the file in scala line by line with
Source.fromFile(path).getLines()
Now I read it as a whole with
import org.apache.commons.io.FileUtils._
// encoding is null for platform default
val content=readFileToString(new File(path),null.asInstanceOf[String])
which closes the file properly after reading and now
new File(path).delete
works.
FOR Eclipse/NetBeans
Restart your IDE and run your code again this is only trick work for me after one hour long struggle.
Here is my code:
File file = new File("file-path");
if(file.exists()){
if(file.delete()){
System.out.println("Delete");
}
else{
System.out.println("not delete");
}
}
Output:
Delete
Another corner case that this could happen: if you read/write a JAR file through a URL and later try to delete the same file within the same JVM session.
File f = new File("/tmp/foo.jar");
URL j = f.toURI().toURL();
URL u = new URL("jar:" + j + "!/META-INF/MANIFEST.MF");
URLConnection c = u.openConnection();
// open a Jar entry in auto-closing manner
try (InputStream i = c.getInputStream()) {
// just read some stuff; for demonstration purposes only
byte[] first16 = new byte[16];
i.read(first16);
System.out.println(new String(first16));
}
// ...
// i is now closed, so we should be good to delete the jar; but...
System.out.println(f.delete()); // says false!
Reason is that the internal JAR file handling logic of Java, tends to cache JarFile entries:
// inner class of `JarURLConnection` that wraps the actual stream returned by `getInputStream()`
class JarURLInputStream extends FilterInputStream {
JarURLInputStream(InputStream var2) {
super(var2);
}
public void close() throws IOException {
try {
super.close();
} finally {
// if `getUseCaches()` is set, `jarFile` won't get closed!
if (!JarURLConnection.this.getUseCaches()) {
JarURLConnection.this.jarFile.close();
}
}
}
}
And each JarFile (rather, the underlying ZipFile structure) would hold a handle to the file, right from the time of construction up until close() is invoked:
public ZipFile(File file, int mode, Charset charset) throws IOException {
// ...
jzfile = open(name, mode, file.lastModified(), usemmap);
// ...
}
// ...
private static native long open(String name, int mode, long lastModified,
boolean usemmap) throws IOException;
There's a good explanation on this NetBeans issue.
Apparently there are two ways to "fix" this:
You can disable the JAR file caching - for the current URLConnection, or for all future URLConnections (globally) in the current JVM session:
URL u = new URL("jar:" + j + "!/META-INF/MANIFEST.MF");
URLConnection c = u.openConnection();
// for only c
c.setUseCaches(false);
// globally; for some reason this method is not static,
// so we still need to access it through a URLConnection instance :(
c.setDefaultUseCaches(false);
[HACK WARNING!] You can manually purge the JarFile from the cache when you are done with it. The cache manager sun.net.www.protocol.jar.JarFileFactory is package-private, but some reflection magic can get the job done for you:
class JarBridge {
static void closeJar(URL url) throws Exception {
// JarFileFactory jarFactory = JarFileFactory.getInstance();
Class<?> jarFactoryClazz = Class.forName("sun.net.www.protocol.jar.JarFileFactory");
Method getInstance = jarFactoryClazz.getMethod("getInstance");
getInstance.setAccessible(true);
Object jarFactory = getInstance.invoke(jarFactoryClazz);
// JarFile jarFile = jarFactory.get(url);
Method get = jarFactoryClazz.getMethod("get", URL.class);
get.setAccessible(true);
Object jarFile = get.invoke(jarFactory, url);
// jarFactory.close(jarFile);
Method close = jarFactoryClazz.getMethod("close", JarFile.class);
close.setAccessible(true);
//noinspection JavaReflectionInvocation
close.invoke(jarFactory, jarFile);
// jarFile.close();
((JarFile) jarFile).close();
}
}
// and in your code:
// i is now closed, so we should be good to delete the jar
JarBridge.closeJar(j);
System.out.println(f.delete()); // says true, phew.
Please note: All this is based on Java 8 codebase (1.8.0_144); they may not work with other / later versions.

Categories