Existing File Copy?

P

P.Hill

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
 
C

Chris Smith

P.Hill said:
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
 
P

P.Hill

Chris said:
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
 
M

Marco Schmidt

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
 
C

Chris Smith

P.Hill said:
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
 
P

P.Hill

Marco said:
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.
 
C

Chris Smith

Marco said:
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
 
G

Guest

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


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
 
M

Marco Schmidt

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
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top