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
    Matt, Nov 16, 2008
    #1
    1. Advertising

  2. On Nov 17, 10:12 am, Matt <> wrote:
    > Can somebody explain to me why file output doesn't work unless the
    > file is closed explicitly?
    >


    try

    > {
    >         PrintWriter pw = new PrintWriter(new File("test.txt"));
    >         pw.print("Hello world!");


    pw.flush();

    >         pw.close();  // necessary?
    >
    > }


    catch (...)

    finally ...

    > Shouldn't files be closed by the OS when the program ends?  


    Of course files are 'closed' when the Java program
    that had them loaded, has exited. No program has
    them open, so they are closed.

    >...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?


    Java was designed for robustness, extensibility
    and performance, rather than lazy programmers?

    --
    Andrew Thompson
    http://pscode.org/
    Andrew Thompson, Nov 16, 2008
    #2
    1. Advertising

  3. Matt wrote:
    > 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?
    > }


    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.

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


    Because PrintWriter.close() flushes the stream first but the OS's
    closing doesn't flush the stream.

    > 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.


    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.

    > 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?


    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
    output.

    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.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, Nov 16, 2008
    #3
  4. On Nov 16, 6:12 pm, Matt <> wrote:
    > 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"));


    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 {

    >         pw.print("Hello world!");


    } finally {
    >         pw.close();  // necessary?

    }

    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.
    >
    > }
    >
    > Shouldn't files be closed by the OS when the program ends?  If so, why
    > doesn't the file ever get written?


    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.

    > 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.


    Don't do this. Finalize is never guaranteed to be called and
    overriding it slows down garbage collection for passes involving
    finalizable objects.

    > 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?


    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
    writer.

    -o
    Owen Jacobson, Nov 16, 2008
    #4
  5. Matt

    Matt Guest

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

    Matt
    Matt, Nov 17, 2008
    #5
  6. Matt

    Arne Vajhøj Guest

    Joshua Cranmer wrote:
    > Matt wrote:
    >> 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?
    >> }

    >
    > 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.


    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
    Arne Vajhøj, Nov 17, 2008
    #6
  7. Arne Vajhøj wrote:
    > Joshua Cranmer wrote:
    >> 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.

    >
    > 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.


    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.

    > 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.


    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.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, Nov 17, 2008
    #7
  8. Matt

    Arne Vajhøj Guest

    Joshua Cranmer wrote:
    > Arne Vajhøj wrote:
    >> Joshua Cranmer wrote:
    >>> 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.

    >>
    >> 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.

    >
    > 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.
    >
    >> 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.

    >
    > 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.


    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
    Arne Vajhøj, Nov 17, 2008
    #8
  9. Matt

    Arne Vajhøj Guest

    Arne Vajhøj wrote:
    > Joshua Cranmer wrote:
    >> Arne Vajhøj wrote:
    >>> Joshua Cranmer wrote:
    >>>> 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.
    >>>
    >>> 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.

    >>
    >> 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.
    >>
    >>> 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.

    >>
    >> 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.

    >
    > 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.


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

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

    J. Davidson Guest

    Joshua Cranmer wrote:
    > 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.


    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
    #10
  11. Matt

    J. Davidson Guest

    J. Davidson wrote:
    > Joshua Cranmer wrote:
    >> 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.

    >
    > Anyone want to know why there's two layers of buffering in Java?


    Darn, no bold here? Oh well ...

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

    Lars Enderin Guest

    J. Davidson skrev:
    > J. Davidson wrote:
    >> Joshua Cranmer wrote:
    >>> 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.

    >>
    >> Anyone want to know why there's two layers of buffering in Java?

    >
    > Darn, no bold here? Oh well ...
    >

    *Bold* works for me.
    Lars Enderin, Nov 17, 2008
    #12
  13. J. Davidson wrote:
    > Anyone want to know why there's two layers of buffering in Java?


    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
    asterisks.*

    > 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.


    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.

    > 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.


    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.
    >
    > 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



    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, Nov 17, 2008
    #13
  14. Matt

    Lew Guest

    J. Davidson wrote:
    >> Darn, no bold here? Oh well ...


    Lars Enderin wrote:
    > *Bold* works for me.


    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
    Lew, Nov 17, 2008
    #14
  15. Matt

    Lew Guest

    J. Davidson wrote:
    >> 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.


    Joshua Cranmer <> wrote:
    > 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.


    "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
    Lew, Nov 17, 2008
    #15
  16. Lew wrote:
    > Fifty years from now hard disks will be obsolete.


    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.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, Nov 17, 2008
    #16
  17. Matt

    Roedy Green Guest

    On Sun, 16 Nov 2008 15:12:06 -0800 (PST), Matt <>
    wrote, quoted or indirectly quoted someone who said :

    >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?
    >}
    >


    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 http://mindprod.com/jgloss/finalize.html There in no guarantee
    finalizers will ever be run.

    --
    Roedy Green Canadian Mind Products
    http://mindprod.com
    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
    #17
  18. On Mon, 17 Nov 2008 07:32:59 -0800, Lew wrote:

    > J. Davidson wrote:
    >>> 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.

    >
    > Joshua Cranmer <> wrote:
    >> 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.

    >
    > "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.


    ....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@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
    Martin Gregorie, Nov 17, 2008
    #18
  19. Matt

    Tom Anderson Guest

    On Mon, 17 Nov 2008, Martin Gregorie wrote:

    > On Mon, 17 Nov 2008 07:32:59 -0800, Lew wrote:
    >
    >> J. Davidson wrote:
    >>>> 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.

    >>
    >> Joshua Cranmer <> wrote:
    >>> 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.

    >>
    >> "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.

    >
    > ...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.


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

    tom

    --
    Work alone does not suffice: the efforts must be intelligent. -- Charles
    B. Rogers
    Tom Anderson, Nov 17, 2008
    #19
  20. Matt

    Lew Guest

    Lew wrote:
    >> Fifty years from now hard disks will be obsolete.


    Martin Gregorie wrote:
    > ...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.


    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
    paper.

    --
    Lew
    No other virtual reality system has been invented that outperforms the
    novel, given a trained user.
    Lew, Nov 17, 2008
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Paul J. Lucas
    Replies:
    117
    Views:
    12,555
    Tim Tyler
    Sep 27, 2005
  2. =?Utf-8?B?Vk1J?=

    Closing popup window when closing parent window?

    =?Utf-8?B?Vk1J?=, Feb 14, 2007, in forum: ASP .Net
    Replies:
    3
    Views:
    652
    Thomas Hansen
    Feb 15, 2007
  3. andrey
    Replies:
    0
    Views:
    160
    andrey
    Dec 15, 2007
  4. Andrey Nikitin
    Replies:
    1
    Views:
    168
    Nobuyoshi Nakada
    Dec 16, 2007
  5. thomas
    Replies:
    0
    Views:
    226
    thomas
    Oct 23, 2003
Loading...

Share This Page