Existing File Copy?

Discussion in 'Java' started by P.Hill, Jan 8, 2004.

  1. P.Hill

    P.Hill Guest

    So is there a standard API for MOVING a file?
    I have a Java program that finishes by pushing a file
    to a server and I'd prefer not to exec() if there is
    some standard or already written way even in this case
    if it changes the file date(s).

    File.renameTo() says:
    "Whether or not this method can move a file from one filesystem to another is
    platform-dependent."

    there is no File.move.

    how about something in?
    http://www.tolstoy.com/samizdat/jconfig.html

    Anything else?
    -Paul
    P.Hill, Jan 8, 2004
    #1
    1. Advertising

  2. P.Hill

    Chris Smith Guest

    P.Hill wrote:
    > So is there a standard API for MOVING a file?
    > I have a Java program that finishes by pushing a file
    > to a server and I'd prefer not to exec() if there is
    > some standard or already written way even in this case
    > if it changes the file date(s).
    >
    > File.renameTo() says:
    > "Whether or not this method can move a file from one filesystem to another is
    > platform-dependent."
    >
    > there is no File.move.


    It's unfortunate that this functionality doesn't exist in the File
    class. Here's a quick implementation... try playing around with
    BUFFER_SIZE if performance is important to you.

    public void move(File source, File dest) throws IOException
    {
    final int BUFFER_SIZE = 32768;
    InputStream in = new FileInputStream(source);

    try
    {
    OutputStream out = new FileOutputStream(dest);

    try
    {
    byte[] buffer = new byte[BUFFER_SIZE];
    int len;

    while ((len = in.read(buffer)) > 0)
    {
    out.write(buffer, 0, len);
    }
    }
    finally
    {
    out.close();
    }
    }
    finally
    {
    in.close();
    }
    }

    --
    www.designacourse.com
    The Easiest Way to Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
    Chris Smith, Jan 8, 2004
    #2
    1. Advertising

  3. P.Hill

    P.Hill Guest

    Chris Smith wrote:
    > P.Hill wrote:
    > It's unfortunate that this functionality doesn't exist in the File
    > class. Here's a quick implementation... try playing around with
    > BUFFER_SIZE if performance is important to you.
    >
    > public void move(File source, File dest) throws IOException


    Technically Chris provided a file COPY method.
    but that is easily fixed by changing its name to copy and adding:

    public static void move( File source, File dest ) throws IOException {
    copy( source, dest );
    boolean deleted = source.delete();
    if ( !deleted ) {
    throw new IOException( "Unable to delete file " +
    source.getCanonicalPath() );
    }
    }

    Thanks Chris! You are write, why not just do it myself (or copy your routine
    in some util class that I have).

    -Paul
    P.Hill, Jan 8, 2004
    #3
  4. P.Hill:

    [...]
    >File.renameTo() says:
    >"Whether or not this method can move a file from one filesystem to another is
    >platform-dependent."
    >
    >there is no File.move.


    I was told that moving between different partitions with File.renameTo
    now seems to work under Sun JDK/Windows. Within a partition it has
    always worked as far as I know. Try it with your server, maybe it is
    implemented for non-Windows JREs as well. Or maybe your server is
    running Windows anyway.

    Regards,
    Marco
    --
    Please reply in the newsgroup, not by email!
    Java programming tips: http://jiu.sourceforge.net/javatips.html
    Other Java pages: http://www.geocities.com/marcoschmidt.geo/java.html
    Marco Schmidt, Jan 8, 2004
    #4
  5. P.Hill

    Chris Smith Guest

    P.Hill wrote:
    > Technically Chris provided a file COPY method.


    Oops! I intended to provide a move method, then got distracted and
    wrote a routine to copy instead. I'm going to feel dumb for a while
    now. :)

    > but that is easily fixed by changing its name to copy and adding:
    >
    > public static void move( File source, File dest ) throws IOException {
    > copy( source, dest );
    > boolean deleted = source.delete();
    > if ( !deleted ) {
    > throw new IOException( "Unable to delete file " +
    > source.getCanonicalPath() );
    > }
    > }


    Or I'd prefer this:

    public static void move(File source, File dest) throws IOException
    {
    if (!source.renameTo(dest))
    {
    // Your code above
    }
    }

    --
    www.designacourse.com
    The Easiest Way to Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
    Chris Smith, Jan 8, 2004
    #5
  6. P.Hill

    P.Hill Guest

    Marco Schmidt wrote:
    > I was told that moving between different partitions with File.renameTo
    > now seems to work under Sun JDK/Windows. Within a partition it has
    > always worked as far as I know. Try it with your server, maybe it is
    > implemented for non-Windows JREs as well.


    To late, I'm already done with the unit test and have little interest
    in testing whether File.rename(...) will work over a _network_ mount from
    windows to/from Linux, but here is a test case if you want to give it a try.
    If someone does this, let me know what you find out for Linux, Unix and
    Windows.

    public void testCopyAndMove() throws IOException {
    String testDir = "test\\phill\\";
    File from = new File( testingRoot + testDir + "aFile.txt" );
    String toCopyName = remoteRoot + testDir + "aFileCopy.txt";
    String toMoveName = testingRoot + testDir + "aFileMove.txt";
    File toCopy = new File( toCopyName );
    File toMove = new File( toMoveName );
    FileUtil.copy( from, toCopy );
    Assert.assertTrue( "Expected a copy of " + from + " to exist at " +
    toCopyName, toCopy.exists() );
    FileUtil.move( toCopy, toMove);
    Assert.assertTrue( "Expected the file " + toCopyName + " to now be at "
    + toMoveName, toMove.exists() );
    toMove.delete();
    }

    > Or maybe your server is
    > running Windows anyway.


    One server? Ha! I needed it to work on Linux and Windows.

    thanks again to Chris,
    -Paul
    p.s. I put the check in for identity of to and from.
    P.Hill, Jan 8, 2004
    #6
  7. P.Hill

    Chris Smith Guest

    Marco Schmidt wrote:
    > I was told that moving between different partitions with File.renameTo
    > now seems to work under Sun JDK/Windows. Within a partition it has
    > always worked as far as I know. Try it with your server, maybe it is
    > implemented for non-Windows JREs as well. Or maybe your server is
    > running Windows anyway.


    This brings up an interesting problem. The documentation makes it clear
    that this is not guaranteed to work, and we've seen that even if it does
    now work on the target operating system, the functionality may depend on
    the exact version of the Java runtime in use. On the other hand, it may
    well be political suicide for Sun to remove that functionality now; even
    though they would still be providing a correct implementation of the
    Java platform API.

    So the question: if you do only need the application to work on one
    specific and testable operating system, do you trust the political
    motivations involved and assume that renameTo will work across these
    kinds of boundaries, or do you just bite the bullet and write code
    that's guaranteed to be correct on any implementation of the Java
    platform? I'm voting for the latter.

    --
    www.designacourse.com
    The Easiest Way to Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
    Chris Smith, Jan 8, 2004
    #7
  8. On Thu, 08 Jan 2004 12:34:03 -0700, Chris Smith wrote:

    > P.Hill wrote:
    >> Technically Chris provided a file COPY method.

    >
    > Oops! I intended to provide a move method, then got distracted and
    > wrote a routine to copy instead. I'm going to feel dumb for a while
    > now. :)
    >
    >> but that is easily fixed by changing its name to copy and adding:
    >>
    >> public static void move( File source, File dest ) throws IOException {
    >> copy( source, dest );
    >> boolean deleted = source.delete();
    >> if ( !deleted ) {
    >> throw new IOException( "Unable to delete file " +
    >> source.getCanonicalPath() );
    >> }
    >> }

    >
    > Or I'd prefer this:
    >
    > public static void move(File source, File dest) throws IOException
    > {
    > if (!source.renameTo(dest))
    > {
    > // Your code above
    > }
    > }



    While we're doing it, let's do it right!

    If dest in copy or move is a directory, we should append source.getName().
    This makes it function the same as in *nix and Windows.

    Also, if dest already exists in move, it should throw an exception.

    One last improvement - make copy recursive if called on a directory. To
    avoid infinite recursion, create a private helper function that keeps
    track of the directories already traversed.

    public static void move(File source, File dest) throws IOException
    {
    if ( dest.isDirectory() )
    {
    dest = new File( dest, source.getName() );
    }
    if ( dest.exists() )
    {
    throw new IOException();
    }
    if (! source.renameTo( dest) )
    {
    copy( source, dest );
    if (! source.delete() )
    {
    throw new IOException();
    }
    }
    }

    private void copy( File source, File dest, Set visited) throws IOException
    {
    if ( visited == null )
    {
    visited = new HashSet();
    }
    if ( visited.contains( source.getCanonicalPath() )
    {
    return; // already been here
    }
    if (! dest.exists() )
    {
    dest.mkdirs();
    }
    else if (! dest.isDirectory() )
    {
    throw new IOException();
    }
    visited.add( source.getCanonicalPath() );
    File children[] = source.getFiles();
    for ( int i=0; i < children.length; i++ ) {
    if ( children.isDirectory() )
    {
    copy( children, new File( dest, children.getName(), visited);
    }
    else
    {
    copy( children, dest );
    }
    }
    }

    public static void copy( File source, File dest) throws IOException
    {
    if ( dest.isDirectory() )
    {
    dest = new File( dest, source.getName() );
    }
    if ( source.isDirectory() )
    {
    copy(source, dest, null);
    return;
    }
    File parent = dest.getParentFile();
    if ( parent != null && ! parent.exists() )
    {
    parent.mkdirs();
    }
    // do a simple copy using streams on source and dest
    }

    If anyone has any more suggestions, I would appreciate an email (just
    remove _this_ from the addy used in the header).

    HTH,
    La'ie Techie
    =?UTF-8?b?TMSByrtpZSBUZWNoaWU=?=, Jan 9, 2004
    #8
  9. Chris Smith:

    [...]

    >So the question: if you do only need the application to work on one
    >specific and testable operating system, do you trust the political
    >motivations involved and assume that renameTo will work across these
    >kinds of boundaries, or do you just bite the bullet and write code
    >that's guaranteed to be correct on any implementation of the Java
    >platform? I'm voting for the latter.


    Definitely, yes, unless it's a hobbyist project nobody else ever gets
    to see. It's a pity that Sun never thought file copying and moving to
    be worth adding to the API. Obviously the data copying can be
    implemented in pure Java, but the metadata - file creation date,
    comments that may be stored in the file system, OS-specific items -
    get lost.

    Regards,
    Marco
    --
    Please reply in the newsgroup, not by email!
    Java programming tips: http://jiu.sourceforge.net/javatips.html
    Other Java pages: http://www.geocities.com/marcoschmidt.geo/java.html
    Marco Schmidt, Jan 9, 2004
    #9
    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. nrm
    Replies:
    3
    Views:
    527
  2. Alex
    Replies:
    2
    Views:
    1,223
  3. Replies:
    26
    Views:
    2,112
    Roland Pibinger
    Sep 1, 2006
  4. Martin Martinos
    Replies:
    3
    Views:
    125
    Martin Martinos
    Nov 7, 2006
  5. Replies:
    0
    Views:
    185
Loading...

Share This Page