package com.mycompany.mavenproject1;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.math.BigDecimal;
public class Main {
public BufferedWriter writer;
public Main() {
Charset charset = Charset.forName("US-ASCII");
try {
this.writer = Files.newBufferedWriter(Paths.get("test.txt"), charset);
} catch (IOException e) {
System.err.format("IOException: %s%n", e);
}
}
public void print_fees(String msg, BigDecimal b) {
try {
int msg_len = msg.length();
int t;
t = 34 - msg_len;
t = t - 6;
this.writer.write(msg + String.format("%" + t + "s", b));
this.writer.newLine();
} catch (IOException e) {
System.err.format("IOException: %s%n", e);
}
}
public static void main(String args[]) {
BigDecimal b = new BigDecimal(2);
Main obj = new Main();
try {
obj.print_fees("Fee: ", b);
} catch (Exception e) {
System.err.format("Exception: %s%n", e);
}
}
}
Why isn't BufferedWriter writing into file?
The point of BufferedWriter is to buffer written content into memory prior to writing it to whatever underlying implementation. When the buffer is filled in memory, it will write in bulk. This generally improves performance of writing, as doing a direct file/disk write for each small write can kill performance due to I/O blocking.
You need to flush the stream explicitly to indicate you want the entire buffer in memory to be written to the underlying implementation (in this case, a file writer) by invoking BufferedWriter#flush() after you have written to the writer. For example,
this.writer.flush().
Also, you should make a habit of closing open OutputStreams/Writers when you are done with them with BufferedWriter#close(). BufferedWriter will automatically invoke BufferedWriter#flush() for you, writing all your writes to whatever the underlying implementation is, without needing to explicitly invoke BufferedWriter#flush(). For example, close your writer once you have finished writing to your Writer: this.writer.close()
this.writer.write(msg + String.format("%" + t + "s", b));
this.writer.flush();
Related
Here is the code, in which I'm trying to write using Filewriter. This is working fine.
File f2 = new File("Path");
f2.createNewFile();
FileWriter writing = new FileWriter(f2);
writing.write("i'm into you , i'm into you");
writing.flush();
In the following code, I'm trying to write using bufferedwriter. This is not adding any text into the same file. For different file, it is working.
BufferedWriter buffwrite = new BufferedWriter(writing); buffwrite.write("java");
writing.flush();
Yes, definitely you can write both in same class.
Your code is not adding any text into the same file because you are Flushing out FileWriter before BufferedWriter. I just edited your code as below and it worked fine.
File f2 = new File("Path");
f2.createNewFile();
FileWriter writing = new FileWriter(f2);
writing.write("i'm into you , i'm into you");
BufferedWriter buffwrite = new BufferedWriter(writing);
buffwrite.write("java");
buffwrite.flush();//flush BufferedWriter first followed by FileWriter
writing.flush();
You should close the resources your opened: FileWriter writing and BufferedWriter buffwrite. This (JavaDoc)
Flushes the stream. If the stream has saved any characters from the
various write() methods in a buffer, write them immediately to their
intended destination. Then, if that destination is another character
or byte stream, flush it. Thus one flush() invocation will flush all
the buffers in a chain of Writers and OutputStreams.
The right way is to use the try-resource statement. This will tale care to close opened resources.
Or use the java.nio.file.Files.write methods which will do the resource handling.
These IO related classes are designed based on decorator pattern.
If you refer to the BufferedWriter class javadoc, you'd find a constructor that takes a Writer type object. Writer is an abstract class which is extended by FileWriter among other classes. Pass your FileWriter object in the constructor and then call the write (...) and flush methods of BufferedWriter.
All IO classes work in this pattern.
Yes you can write.Please checkout the below usecases for writing file in java using FileWriter, BufferedWriter, FileOutputStream and Files in java.
package com.journaldev.files;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
public class WriteFile {
/**
* This class shows how to write file in java
* #param args
* #throws IOException
*/
public static void main(String[] args) {
String data = "I will write this String to File in Java";
int noOfLines = 10000;
writeUsingFileWriter(data);
writeUsingBufferedWriter(data, noOfLines);
writeUsingFiles(data);
writeUsingOutputStream(data);
System.out.println("DONE");
}
/**
* Use Streams when you are dealing with raw data
* #param data
*/
private static void writeUsingOutputStream(String data) {
OutputStream os = null;
try {
os = new FileOutputStream(new File("/Users/pankaj/os.txt"));
os.write(data.getBytes(), 0, data.length());
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Use Files class from Java 1.7 to write files, internally uses OutputStream
* #param data
*/
private static void writeUsingFiles(String data) {
try {
Files.write(Paths.get("/Users/pankaj/files.txt"), data.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Use BufferedWriter when number of write operations are more
* It uses internal buffer to reduce real IO operations and saves time
* #param data
* #param noOfLines
*/
private static void writeUsingBufferedWriter(String data, int noOfLines) {
File file = new File("/Users/pankaj/BufferedWriter.txt");
FileWriter fr = null;
BufferedWriter br = null;
String dataWithNewLine=data+System.getProperty("line.separator");
try{
fr = new FileWriter(file);
br = new BufferedWriter(fr);
for(int i = noOfLines; i>0; i--){
br.write(dataWithNewLine);
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
br.close();
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Use FileWriter when number of write operations are less
* #param data
*/
private static void writeUsingFileWriter(String data) {
File file = new File("/Users/pankaj/FileWriter.txt");
FileWriter fr = null;
try {
fr = new FileWriter(file);
fr.write(data);
} catch (IOException e) {
e.printStackTrace();
}finally{
//close resources
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I met a problem with BufferedWriter when I write data to a single file with some threads.
I set the buffer size of the BufferedWriter, but no matter what number I set, it flushes the data to disk when the buffer is 8192 (the default buffer size), not the size I set (here is 16384). Is there a problem with my code?
This is how I'm constructing the BufferedWriter:
new BufferedWriter(new FileWriter(fileName, true), 16384);
This is the full code:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Test1 {
public static void main(String[] args) throws IOException {
for(int i =0;i<10;i++){
MyThread r = new MyThread();
Thread t = new Thread(r);
t.start();
}
}
}
class MyThread implements Runnable {
public void run() {
String s = "{addffffffkkkljlkj2015dd}\n";
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(
"/Users/liaoliuqing/Downloads/1.txt", true),16384);
} catch (IOException e) {
e.printStackTrace();
}
for(int i =0 ; i<1000; i++){
try {
bw.write(String.format("%03d", i)+s);
//bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Is there a problem with my code?
A few. Mainly: potential IO and concurrency errors. File buffer size might be a lesser concern (and one you can't effectively deal with).
Trying to open already opened file. All your threads are trying to write into the same file (1.txt). That might be an issue. FileWriter documentation says:
Some platforms, in particular, allow a file to be opened for writing by only one FileWriter (or other file-writing object) at a time. In such situations the constructors in this class will fail if the file involved is already open.
Lines might be cut and mixed. If you have several threads with their respective buffers flushing at some point into the same output, you might not even need weird race-conditions or threads stopped right of the middle or a write operation to see your output corrupted.
As I solution (If your threads must share the same output) you can use a shared object with synchronized access to take care of actual writing. I implemented SafeAppender in my example, but probably there are better alternatives out there.
No flushing and closing buffers will mean (the tail of) your data will be lost (like tears in the rain). A finally block is usually good to take care of that.
Also, as stated by other users, BufferedWriter buffer size does not affect the buffer size in FileOutputStream (and so FileWriter). And it looks the java.io and java.nio APIs dont offer any way to mess with that. If you look at the Java library sources you might notice BufferedWriter buffer size just means the amount of chars you store before actually writing into the delegate output. The default size (8192) is optimal for most cases, and increasing it might mean more trouble (potentially losing more data) than benefits.
This is my code, if it serves you:
// http://stackoverflow.com/questions/32451526/how-to-set-the-buffer-size-on-a-bufferedwriter-over-a-filewriter
public class TestWriter {
public static class SafeAppender {
private BufferedWriter bw;
private int users = 0;
public SafeAppender(File f) throws IOException {
bw = new BufferedWriter(new FileWriter(f));
}
public synchronized void append(String s) throws IOException {
bw.write(s);
}
public synchronized void incrUsers() {
users ++;
}
public synchronized void decrUsers() {
if (--users <= 0) {
try {
bw.flush();
System.err.println("INFO-appender-flush()");
} catch (Throwable whatever) { /* log-if-you-care*/}
}
}
// Might be called by GC, or not
#Override protected void finalize() throws Throwable {
try {
bw.close();
System.err.println("INFO-appender-close()");
} catch (Throwable whatever) { /* log-if-you-care */}
super.finalize();
}
}
private static class MyRunnable implements Runnable {
final static String S = "{addffffffkkkljlkj2015dd}";
SafeAppender appender;
String threadId;
public MyRunnable (SafeAppender a, String tid) {
appender = a; threadId = tid;
}
public void run() {
appender.incrUsers();
try {
for(int i =0 ; i<1000; i++){
// NOTE: Not a good idea to printStackTrace if each line fails. Let thread fail
String line = String.format("%s-%03d-%s\n", threadId, i, S);
appender.append(line);
}
} catch (IOException e) {
System.err.printf("ERROR-%s-%s\n", threadId, e.toString());
} finally {
appender.decrUsers();
}
}
}
public static void main(String[] args) {
try {
File f = File.createTempFile("TestWriter", ".txt");
System.err.printf("INFO-main-Writing into %s\n", f.getCanonicalPath());
SafeAppender appender = new SafeAppender (f);
for(int i =0;i<10;i++){
MyRunnable r = new MyRunnable(appender, ""+i);
Thread t = new Thread(r);
t.start();
}
} catch (Throwable e) {
e.printStackTrace(System.err);
}
}
}
FileWriter actually uses its own fixed-size 1024 byte buffer. The BufferedWriter on the other hand, show that it uses and 8192 byte buffer size (default), which can be configured by the user to any other desired size.
And to further muddy the waters, the Java 6 implementation of OutputStreamWriter actually delegates to a StreamEncoder, which uses its own buffer with a default size of 8192 bytes. And the StreamEncoder buffer is user-configurable, although there is no way to access it directly through the enclosing OutputStreamWriter.
I solve the problem by using OutputStream, not writer, here is the code:
bw = new BufferedOutputStream(
new FileOutputStream(new File("/Users/liaoliuqing/Downloads/1.txt"),true),165537);
What you are seeing is not the size of the buffer BufferedWriter, but the size of the buffer used internally by FileWriter. Quoting from the Java Documentation (http://docs.oracle.com/javase/7/docs/api/java/io/FileWriter.html)
The constructors of this class assume that the default character encoding and the default byte-buffer size are acceptable. To specify these values yourself, construct an OutputStreamWriter on a FileOutputStream.
So if you wanted to have a fine grain control on when the data is actually written to the disk you should instantiate your BufferedWriter as
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File('my_file.txt),true)));
I was testing out writing to files with this code:
package files;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
public class FileTest1
{
public static void main(String[] args)
{
try
{
try
{
File f = new File("filetest1.txt");
FileWriter fWrite = new FileWriter(f);
BufferedWriter fileWrite = new BufferedWriter(fWrite);
fileWrite.write("This is a test!");
}
catch(FileNotFoundException e)
{
System.out.print("A FileNotFoundException occurred!");
e.printStackTrace();
}
}
catch(IOException e)
{
System.out.println("An IOException occurred!:");
e.printStackTrace();
}
}
}
Nothing happens when it is executed.
"This is a test!" is not written, nor the StackTrace or the "A/An [exception] occurred!"...
I don't know what's causing the problem. I have fileTest1.txt in the package right under the file...
A BufferedWriter does just that, it buffers the output before it is written to the destination. This can make the BufferedWriter faster to use as it doesn't have to write to a slow destination, like a disk or socket, straight away.
The contents will be written when the internal buffer is to full, you flush the Writer or close the writer
Remember, if you open it, you should close it...
For example...
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class TestFileWriter {
public static void main(String[] args) {
try {
BufferedWriter fileWrite = null;
try {
File f = new File("filetest1.txt");
System.out.println("Writing to " + f.getCanonicalPath());
FileWriter fWrite = new FileWriter(f);
fileWrite = new BufferedWriter(fWrite);
fileWrite.write("This is a test!");
fileWrite.flush();
} catch (FileNotFoundException e) {
System.out.print("A FileNotFoundException occurred!");
e.printStackTrace();
} finally {
try {
// Note, BufferedWriter#close will also close
// the parent Writer...
fileWrite.close();
} catch (Exception exp) {
}
}
} catch (IOException e) {
System.out.println("An IOException occurred!:");
e.printStackTrace();
}
try {
BufferedReader br = null;
try {
File f = new File("filetest1.txt");
System.out.println("Reading from " + f.getCanonicalPath());
FileReader fReader = new FileReader(f);
br = new BufferedReader(fReader);
String text = null;
while ((text = br.readLine()) != null) {
System.out.println(text);
}
} catch (FileNotFoundException e) {
System.out.print("A FileNotFoundException occurred!");
e.printStackTrace();
} finally {
try {
// Note, BufferedWriter#close will also close
// the parent Writer...
br.close();
} catch (Exception exp) {
}
}
} catch (IOException e) {
System.out.println("An IOException occurred!:");
e.printStackTrace();
}
}
}
If you are using Java 7, you may like to take a look at try-with-resources
After
fileWrite.write("This is a test!");
you have to flush() the writer. To avoid leaking of resources you should also close() the writer (which automatically flushes it).
So you need to add:
fileWrite.close();
Use BufferedWriter.flush() and BufferedWriter.close(). Additional info here http://docs.oracle.com/javase/7/docs/api/java/io/BufferedWriter.html
You must call close() or at least flush() on the writer in order for the buffer to be really written to the file.
How can I use a command line program from within Java?
I'm trying to pass a graph definition in the dot-language (see Wikipedia) to the interpreter program dot (see GraphViz) through java.
The problem is, that the program does not answer, after I have sent the dot-graph to its InputStream, because it does not know, that I'm finished sending the description.
This is, what I currently have:
package exercise4;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
public class Main {
public static void main(String[] args) {
PrintStream out = System.out;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
final String start =
"strict graph LSR%1$d {\n" +
" node [shape=circle color=lightblue style=filled];\n\n" +
" {rank=same; A--B [label=6];}\n" +
" {rank=same; C--D [label=12]; D--E [label=4];}\n" +
" A--C [label=4]; B--D [label=4]; B--E [label=9];\n\n" +
" node [shape=record color=\"#000000FF\" fillcolor=\"#00000000\"];\n}\n";
Process dot = Runtime.getRuntime().exec("dot -Tsvg");
in = new BufferedReader(new InputStreamReader(System.in));
out = new PrintStream(dot.getOutputStream(), false, "UTF-8");
out.printf(start, 0);
out.flush();
out.close();
while(in.ready()) {
System.out.println(in.readLine());
}
in.close();
dot.destroy();
} catch (UnsupportedEncodingException ex) {
} catch (IOException ex) {
} finally {
out.close();
}
}
}
Looks as if you are reading from the wrong input stream. Have a look at this answer: https://stackoverflow.com/a/4741987/1686330
I use Runtime exec() method to create a subprocess in Java. However, since the subprocess is an interactive program, I need to provide input to it as and when required by it. Also I need to show the output of the subprocess. How can I do this in the simplest possible way?
I was using a StreamGobbler to show the program output using process.getInputStream(). I, however, do not know how to identify when the program is waiting for input and when to provide it input using proc.getOutputStream. How can I do this?
You need to copy the input and output between the subprocess' streams and System streams (System.in, System.out and System.err). This is related to my recent quesion. The best solution I have found so far is:
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.FileChannel;
class StreamCopier implements Runnable {
private InputStream in;
private OutputStream out;
public StreamCopier(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
}
public void run() {
try {
int n;
byte[] buffer = new byte[4096];
while ((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
out.flush();
}
}
catch (IOException e) {
System.out.println(e);
}
}
}
class InputCopier implements Runnable {
private FileChannel in;
private OutputStream out;
public InputCopier(FileChannel in, OutputStream out) {
this.in = in;
this.out = out;
}
public void run() {
try {
int n;
ByteBuffer buffer = ByteBuffer.allocate(4096);
while ((n = in.read(buffer)) != -1) {
out.write(buffer.array(), 0, n);
out.flush();
}
out.close();
}
catch (AsynchronousCloseException e) {}
catch (IOException e) {
System.out.println(e);
}
}
}
public class Test {
private static FileChannel getChannel(InputStream in)
throws NoSuchFieldException, IllegalAccessException {
Field f = FilterInputStream.class.getDeclaredField("in");
f.setAccessible(true);
while (in instanceof FilterInputStream)
in = (InputStream)f.get((FilterInputStream)in);
return ((FileInputStream)in).getChannel();
}
public static void main(String[] args)
throws IOException, InterruptedException,
NoSuchFieldException, IllegalAccessException {
Process process = Runtime.getRuntime().exec("sh -i +m");
Thread outThread = new Thread(new StreamCopier(
process.getInputStream(), System.out));
outThread.start();
Thread errThread = new Thread(new StreamCopier(
process.getErrorStream(), System.err));
errThread.start();
Thread inThread = new Thread(new InputCopier(
getChannel(System.in), process.getOutputStream()));
inThread.start();
process.waitFor();
System.in.close();
outThread.join();
errThread.join();
inThread.join();
}
}
The tricky part here is to extract a channel from System.in. Without this you will not be able to interrupt the thread that reads input when the subprocess terminates.
This approach has a serious drawback: after closing System.in you can no longer read from it. The workaround that I'm currently using is to have a single input redirecting thread used for all subprocesses.
Ask yourself "How do I know when the program wants input when I run it from the command line"? You see what it prompts and enter data based on that prompt. The principle will be the same, except your code will need to interpret the program's output and provide the correct input.
To avoid reinventing the wheel, take a look at ExpectJ and/or Expect4J, which are Java implementations of the venerable *nix Expect tool, which is designed to handle this kind of programmatic interaction.