Files not writing, closing files, finalize()

Discussion in 'Java' started by Matt, Nov 16, 2008.

  1. Matt

    Matt Guest

    Can somebody explain to me why file output doesn't work unless the
    file is closed explicitly?

    PrintWriter pw = new PrintWriter(new File("test.txt"));
    pw.print("Hello world!");
    pw.close(); // necessary?

    Shouldn't files be closed by the OS when the program ends? If so, why
    doesn't the file ever get written?

    I tried making my own class which closes the file in finalize(), but
    that doesn't necessarily get called either, so that's out. There's no
    other destructor type of thing in Java.

    I just don't understand why Java can't close the file for me. All
    other languages do it and this is supposed to be a high level
    language. It actually acts like the file was never opened for writing
    at all. It might truncate the file to 0 bytes, but it never writes
    data to the file unless you manually close it. Can anyone explain why
    the behavior is like this?

    Matt, Nov 16, 2008
    1. Advertisements

  2. pw.flush();
    catch (...)

    finally ...
    Of course files are 'closed' when the Java program
    that had them loaded, has exited. No program has
    them open, so they are closed.
    Java was designed for robustness, extensibility
    and performance, rather than lazy programmers?
    Andrew Thompson, Nov 16, 2008
    1. Advertisements

  3. The actual necessary step is "pw.flush()". If you're flushing, you don't
    need the close. Note that "pw.close()" is actually performing a flush
    for you.
    Because PrintWriter.close() flushes the stream first but the OS's
    closing doesn't flush the stream.
    Finalizers are evil. As you've discovered, they're not always called.
    There are also numerous other problems. In short: eschew finalize() if
    at all possible.
    It's because you're using the API wrong. PrintWriter is a shell around a
    generic Writer to make output easier. If you read the API, you'll notice
    that it states that it buffers the output. The buffer is only guaranteed
    to be committed when it is flushed; the default buffer size appears to
    be 8 KiB, so your measly 10-character string isn't being flushed to the

    Constructing a FileOutputStream under default settings (internally
    performed by the PrintWriter constructor you used) will truncate the
    file, but it doesn't write the data until buffers are flushed (not
    closed). Note that this feature is actually relatively common in
    high-level languages, buffering output data. Remember that something
    like disk access is actually very expensive, so buffering is a
    tremendous boost in speed.

    In short: it's not closing the file, it's flushing the stream when it's
    actually written. It just appears to be the stream closure because
    closure implies a final flush.
    Joshua Cranmer, Nov 16, 2008
  4. Per the PrintWriter javadocs, this constructor creates a PrintWriter
    with automatic flushing completely disabled: text is buffered in RAM
    (internally, by a BufferedWriter) until a certain number of characters
    are written. Nothing is written to the OS until the buffer is full,
    flush() is called, or close() is called.

    You're also missing this:
    try {
    } finally {

    The close is not only necessary, but so necessary that you should make
    sure it's called on all possible code paths - even if pw.print throws
    an exception. Hence the try/finally construct.
    The file is being closed by the OS. However, PrintWriter buffers
    writes internally, either until println is called (for autoflush =
    true) or until the buffer is full or flushed (for autoflush = false).
    The OS has no idea that there's data pending, because your code never
    tells it.
    Don't do this. Finalize is never guaranteed to be called and
    overriding it slows down garbage collection for passes involving
    finalizable objects.
    The underlying FileOutputStream is automatically closed by
    finalization, but none of the other intermediate streams (at last
    count: PrintWriter -> BufferedWriter -> OutputStreamWriter ->
    FileOutputStream) will do anything special when they're garbage-
    collected. If you want to guarantee that things written to the
    PrintWriter are written to the FileOutputStream, flush or close the

    Owen Jacobson, Nov 16, 2008
  5. Matt

    Matt Guest

    Thanks for the replies, everyone. They were very informative.

    Matt, Nov 17, 2008
  6. Matt

    Arne Vajhøj Guest

    Is it ?

    close will flush the Java buffer and call OS close - and OS close
    will flush OS buffer. It seems very likely to work.

    flush will flush the Java buffer and image termination will
    implicit close the file. But is is guaranteed that a image
    termination implicit close will flush the OS buffer ? I would
    have guessed that to be highly OS specific.

    Arne Vajhøj, Nov 17, 2008
  7. By "flushing," I mean from the Java API. Even if the OS is buffering
    (which it most likely is), if the Java does not flush it to the native
    system--which is clearly what is happening here--the OS doesn't see
    anything when it foes to flush.
    I don't profess to be an expert in filesystems, but for the average
    user, an OS flush or close will cause the changes it sees to be
    committed so that it is visible externally. The reality is probably much
    more convoluted.
    Joshua Cranmer, Nov 17, 2008
  8. Matt

    Arne Vajhøj Guest

    I will not call myself an expert in that area either.

    But calling close instead of flush in Java sounds much more safe
    to me regarding getting the OS buffer written to the plates.

    Arne Vajhøj, Nov 17, 2008
  9. Matt

    Arne Vajhøj Guest

    Unless there is something in the contracts for Java flush and close
    that I am not aware of. Which is absolutely a possibility.

    Arne Vajhøj, Nov 17, 2008
  10. Matt

    J. Davidson Guest

    Anyone want to know why there's two layers of buffering in Java?
    It's not that Java doesn't trust the OS buffering. It's because each
    trip through JNI to call an OS API routine is expensive.

    So Java buffers because each JNI call is expensive. Then the OS buffers
    because each disk write is expensive.

    Another fifty years from now we'll probably have a big teetering tower
    of abstractions and I/O will get buffered at six or seven layers instead
    of just two.

    Wait, make that three. I think most modern disk controllers do some
    buffering of their own, because waiting for the right spot on a platter
    to rotate under the write head is expensive, and waiting for the head to
    move to a different cylinder is even more expensive.

    - jenny
    J. Davidson, Nov 17, 2008
  11. Matt

    J. Davidson Guest

    Darn, no bold here? Oh well ...

    - jenny
    J. Davidson, Nov 17, 2008
  12. Matt

    Lars Enderin Guest

    J. Davidson skrev:
    *Bold* works for me.
    Lars Enderin, Nov 17, 2008
  13. This is not phpBB. This is Usenet, which is generally pure text. The
    standard way of indicating boldness in pure text is with *a pair of
    I'm not an expert as to where the buffering is, but I'm pretty sure the
    call to the OS-level write routines are expensive in and of themselves.
    So? There's already high-level API buffering, filesystem buffering, and
    probably disk-level buffering as well. As long as they can be reasonably
    guarded against concurrency issues, there's no problem.
    Joshua Cranmer, Nov 17, 2008
  14. Matt

    Lew Guest

    By design, Usenet is supposed to be usable in raw text mode. It is
    bad form to embed HTML, so we use conventions like slash for /italics/
    and asterisk for *bold*. Some newsreaders interpret those
    conventions, and even grey out sigs set off by "dash dash space" ("--
    ") on a line by itself. That is up to the newsreader. The rest of us
    do it by imagination.
    Lew, Nov 17, 2008
  15. Matt

    Lew Guest

    "Disks are a hack."
    - Alan Cooper, /About Face/

    Disks are a hack because it's too expensive to buy a terabyte of
    static RAM.

    Fifty years from now hard disks will be obsolete.
    Lew, Nov 17, 2008
  16. Predictions of obsolescence tend to be woefully underestimated. After
    all, the magnetic tape has not died its death yet.

    I predict that fifty years from now, some people will be using hard
    disks, by necessity. It may evolve into a niche role (like magnetic
    tape), but it will still have one nonetheless.
    Joshua Cranmer, Nov 17, 2008
  17. Matt

    Roedy Green Guest

    Looks ok. Try being more explicit where the file is written by
    specifying drive and dir. Dump out the CWD, it may not be where you
    expect. That it where test.txt will show up.

    Also try a println not print. Your editor you using to look at the
    file might not be happy with the missing terminator.

    Even if the file were to close eventually automatically, you want to
    release the considerable resources for it as soon as possible.

    See There in no guarantee
    finalizers will ever be run.

    Roedy Green Canadian Mind Products
    Your old road is
    Rapidly agin'.
    Please get out of the new one
    If you can't lend your hand
    For the times they are a-changin'.
    Roedy Green, Nov 17, 2008
  18. ....only if somebody designs reliable non-volatile RAM with either a multi-
    decade storage and read-only lifetime or at least a million-fold increase
    in the number of write cycles it can handle without failing.
    Martin Gregorie, Nov 17, 2008
  19. Matt

    Tom Anderson Guest

    Wrong. Because tape's going to make a comeback - I GUARANTEE IT!

    Tom Anderson, Nov 17, 2008
  20. Matt

    Lew Guest

    Or they develop a different form of offline storage with better
    performance than hard drives and higher capacity, which I deem
    extremely likely. RAM and hard drives are not the only two ways to
    store data even today, so I figure other technologies are just around
    the corner, and that doesn't even account for ideas not yet
    conceived. Fifty years is eons of innovation in I.T. and electronics.

    I have yet to have a hard drive last one decade, much less multiple
    decades, so that part of the argument leaves me cold. I know of no
    serious project that doesn't back up its hard drives, so I figure my
    experience isn't unique.

    So I take exception to the "only if" part of your argument.
    Additionally, someone very well might come up with "reliable non-
    volatile RAM with either a multi-decade storage and read-only lifetime
    [which would then be better than hard drives are now][,] or at least a
    million-fold increase in the number of write cycles it can handle
    without failing."

    So far no electronic medium exceeds the read-only lifetime of ink on
    Lew, Nov 17, 2008
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.