0

There are so many Input/Output Classes in Java. It is really a mess. You do not know which to use. Which functions does operating system offer ? There will be one to read one byte of a file or many bytes of a file I guess.

So for example if I use this.

String path = "C:\\Users\\myName\\test.txt";
FileOutputStream fos = new FileOutputStream(path);
fos.write(333);

If I open it with a text editor it shows me letter "G" . Already I do not understand this.

And this code does not write anything, the file is empty weirdly.

String path = "C:\\Users\\myName\\test.txt";
FileOutputStream fos = new FileOutputStream(path);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fos));
out.write("something");

All these I/O classes just confuse me. What does buffered mean. It reads 1000 Bytes at once. So there is operating function to straight away read 1000 Bytes of a file I guess.

Alicia22
  • 1
  • 1
  • call flush on the stream. fos.flush() – Soni Sep 19 '20 at 16:24
  • Close `fos` and `out`. – Spectric Sep 19 '20 at 16:26
  • 3
    Does this answer your question? [How do I create a file and write to it in Java?](https://stackoverflow.com/questions/2885173/how-do-i-create-a-file-and-write-to-it-in-java) – David Buzatu Sep 19 '20 at 16:28
  • As for the 'G', you wrote a number and tried to read it as an ASCII field. – cliff2310 Sep 19 '20 at 16:30
  • @ soni Kumari you have to flush out. If you flush fos it will not work. @cliff2310 no I wrote byte , not a number – Alicia22 Sep 19 '20 at 16:53
  • Looks like BufferedWriter.wirte method only writes to buffer but not to file – Alicia22 Sep 19 '20 at 16:55
  • You may want to read a [file writing tutorial](https://docs.oracle.com/javase/tutorial/essential/io/file.html) or a least check the [Javadoc](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/io/BufferedOutputStream.html). A buffered writer writes when the buffer is full, that is the whole point of buffering: write in (large) chunks instead of writing each byte on its own, for better performance. You need to flush to force a write (or close the stream, which implicitly flushes). `write(333)` does write a byte, but 333 doesn't fit in a byte, so it gets mangled. – Robert Sep 19 '20 at 17:22

3 Answers3

1

There are so many Input/Output Classes in Java. It is really a mess. You do not know which to use.

The Files class is by far the easiest to use. For instance,

Files.writeString(Paths.get("test.txt"), "hello world!");

creates a text file named "test.txt" containing the text "hello world!".

The other classes are only needed if you want to do something fancy (for instance, deal with files too big to fit in main memory). For instance, suppose you wanted to read a huge log file (hundreds of gigabytes long) and wanted to write each line containing a particular word to another file. If you were to open the file with

Files.readAllLines(Paths.get("huge.log"));

you'd receive an OutOfMemoryError because the file doesn't fit in main memory. To work around that, we must read the file piece-wise, and that is what all those Reader and Writer classes (or InputStream and OutputStream, if you're dealing with binary files) are good for:

    try (
        var reader = Files.newBufferedReader(Paths.get("huge.log"));
        var writer = Files.newBufferedWriter(Paths.get("interesting.log"));
    ) {
        String line;
        while ((line = reader.readLine()) != null) {
            if (line.contains(searchWord)) {
                writer.write(line);
                writer.write('\n');
            }
        }
    }

As you can see, their use is quite a bit more complicated. For one, we must close the Reader and Writer once we are done with them, which is easiest accomplished with the try with resources statement shown above.

Closing is necessary because most operating systems limit the number of files that can be open at once. Closing also gives any Buffered* classes the opportunity to empty their buffers, ensuring that any data still in buffers is passed on to the file system.

If we fail to close, as you did in your example code, the file remains open until our program exits, upon which time any data in the buffers is lost, resulting in the incomplete file you found.

meriton
  • 68,356
  • 14
  • 108
  • 175
0

You need to close the instances of BufferedWriter out and FileOutputStream fos, after invoking the out.write("something"), then only the file gets created successfully with the contents you are trying to write.

     public static void main(String[] args) throws IOException {
         String path = "C:\\Users\\myName\\test.txt";
         FileOutputStream fos = new FileOutputStream(path);
         BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fos));
         out.write("something");
         out.close(); // Closes the stream, flushing it first. 
         fos.close(); // Closes this file output stream and releases any system resources associated with this stream.
        }
John Thomas
  • 212
  • 3
  • 21
  • ok thanks. Closing both was enough. Did not need to flush. But that is weird. Why do I have to close first and only then text gets written in file . Is it because buffer is not full and then it would only get written automatically if buffer is full. – Alicia22 Sep 19 '20 at 16:48
  • You weren't flushing the stream, only after the flush the text gets written in the file. `close()` does the flush and close the streams basically. You could just use `out.flush()` to get the contents into the file. – John Thomas Sep 19 '20 at 17:08
0

Closing the instances of BufferedWriter and FileOutputStream will solve the issue. fos.write(333) => The number has been written to the file and when you open the file it opens in ASCII format. You can use below code.

    public static void main(String[] args) throws IOException {

        FileWriter fw=new FileWriter("D:\\test.txt");
        fw.write("Hello! This is a sample text");
        System.out.println("Writing successful");
        fw.close();

        /* your code
        String path = "D:\\test1.txt";
        FileOutputStream fos = new FileOutputStream(path);
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fos));
        out.write("Hello! This is a sample text");
        out.close(); 
        fos.close();
        */
    }
Pradeep
  • 34
  • 2
  • Aha ok. thanks. when I write 65 , it now shows me "A" in the file. Makes sense. But this is a really weird construct. a BufferdWriter needs an OutputStreamWriter who needs a FileOutputStream. So complicated. – Alicia22 Sep 19 '20 at 17:04
  • Yes, I agree on and it is a bit of complicated and weird implementation. But you will get used to it as you do more programming on file operation in java. – Pradeep Sep 19 '20 at 17:25
  • @Alicia22 A BufferedWriter can write anywhere, not just files: to the network, or into another writer. That's the idea behind these writers: you chain them. Your code just writes to a generic Stream, and doesn't care if that ends up being a zip file, an encrypted file, a plain text file, or an encrypted zipped network connection. This is called polymorphism. – Robert Sep 19 '20 at 17:29
  • You should also close the `Writer` if an exception is thrown. This is easiest accomplished with a try-with-resources statement. Also, beware that `FileWriter` uses the platform default encoding if an encoding is not specified, rather than UTF-8, which can raise portability concerns. – meriton Sep 19 '20 at 17:42
  • new BufferedWriter(new OutputStreamWriter(fos)); Using BufferedWriter in this case is actually not necessary. just OutputStreamWriter would be enough. – Alicia22 Sep 19 '20 at 18:19