aspose file tools*
The moose likes Java in General and the fly likes A Mirroring Algorithm Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "A Mirroring Algorithm" Watch "A Mirroring Algorithm" New topic
Author

A Mirroring Algorithm

K Man
Greenhorn

Joined: Apr 15, 2004
Posts: 10
Hi,
I am trying to write a Java application that basically mirrors the contents of one directory to another directory. In other words, whatever is in one directory must be present in one directory MUST be present in the other directory after the application runs.
Up to this point, I have coded it such that the mirroring of files between src and trg works just fine. However, when trying to implement the mirroring for directories (within the src and trg), I am not able to consistently pass all test cases. If anyone could help me out, that would be appreciated.
Here is my code:
import java.io.File;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.io.*;
public class Mirror
{
public static final void main (String [] args)
throws Exception
{
Mirror mir = new Mirror(
new File("c:/jmirror/src")
, new File("c:/jmirror/trg")
);
}
/**
*/
private void out(Object o) {
System.out.println(o);
}
/**
* The following constructor creates a directory given the File pathname passed to it.
*/
public Mirror(File src)
{
src.mkdir();
}
/** Displays the file names in the directories.
*/
public Mirror(File src, File trg) throws Exception
{
out("JMirror Starting");
File [] srcFiles = this.getFiles(src);
for (int i=0; i<srcFiles.length; i++)
{
out("src: " + srcFiles[i].getName());
if(srcFiles[i].isDirectory())
{
this.display(srcFiles[i]);
}
}
File [] trgFiles = this.getFiles(trg);
for (int i=0; i<trgFiles.length; i++)
{
out("trg: " + trgFiles[i].getName());
if(trgFiles[i].isDirectory())
{
this.display(trgFiles[i]);
}
}
this.mirrorFiles(srcFiles, trg, trgFiles);
}
/** This method recursively displays the contents of a nested directory structure
* within either src or trg directories.
*/
private void display (File fil) throws Exception
{
File [] files = this.getFiles(fil);
for (int i=0; i<files.length; i++)
{
out(files[i].getPath());
if(files[i].isDirectory())
{
this.display(files[i]);
}
}
}
/** This method returns the list of files and directories under the specific file path.
*/
private final File [] getFiles(File f)
{
FileFilter filter = null;

return f.listFiles(filter);
}
/**
*/
private final Map asMap(File [] value)
{
HashMap map = new HashMap();
for (int i=0; i<value.length; i++) {
map.put(value[i].getName(), value[i]);
}
return map;
}
/**
*/
private final void mirrorFiles(File [] srcFiles, File trgFilesRoot, File [] trgFiles)
throws Exception,IOException
{
Map trgMap = this.asMap(trgFiles);
File src;
File trg;
for (int i=0; i<srcFiles.length; i++)
{
src = srcFiles[i];
trg = (File)trgMap.get(src.getName());
/** TROUBLE AT THIS POINT! Trying to handle mirroring of directories
if(src.isDirectory() || (src.isDirectory() &&trg==null) || (src.isDirectory() && src.lastModified() != trg.lastModified()))
{
//Mirror mir2 = new Mirror(new File(src.getPath()), new File(trg.getPath()));
this.copyDirectory(src,new File(trgFilesRoot,src.getName()));
} */


else// If the src directory has something that trg doesnt have, then it's copied to trg.
{
if (!trgMap.containsKey(src.getName())) {
// 1 0
this.copy(src, new File(trgFilesRoot, src.getName()));
}

// If both src and trg have the same file then if the modification times of both files vary,
// then it is copied from src to trg since the file in src represents the latest version.
else {
// 1 1
trg = (File)trgMap.get(src.getName());
if (src.lastModified() != trg.lastModified()) {
this.copy(src, trg);
}
}
}
}
// If trg has something the src doesnt have, then it is wiped out.
Map srcMap = this.asMap(srcFiles);
for (int i=0; i<trgFiles.length; i++)
{
trg = trgFiles[i];
if (!srcMap.containsKey(trg.getName())) {
// 0 1
trg.delete();
}

}
}


// Copies src file to dst file.
// If the dst file does not exist, it is created
private final void copy(File src, File dst) throws IOException
{
out("\nCopying:\nsrc:"+src+"\ntrg:"+dst);
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
dst.setLastModified(src.lastModified());
}
// Copies all files under srcDir to dstDir.
// If dstDir does not exist, it will be created.
private final void copyDirectory(File srcDir, File dstDir) throws IOException
{
out("\nCopying:\nsrc:"+srcDir+"\ntrg:"+dstDir);
if (srcDir.isDirectory()) {
if (!dstDir.exists()) {
dstDir.mkdir();
}

String[] children = srcDir.list();
for (int i=0; i<children.length; i++) {
copyDirectory(new File(srcDir, children[i]),
new File(dstDir, children[i]));
}
dstDir.setLastModified(srcDir.lastModified());
} else {
copy(srcDir, dstDir);
}
}
}
sorry for posting so much code.
thanks,
Krishna
Nicholas Cheung
Ranch Hand

Joined: Nov 07, 2003
Posts: 4982
I think you need to do with recursion. When the File object is a directory, you need to recursively pass it to the method, so that all files and sub-directories inside that directory can be mirrored as well.
Nick


SCJP 1.2, OCP 9i DBA, SCWCD 1.3, SCJP 1.4 (SAI), SCJD 1.4, SCWCD 1.4 (Beta), ICED (IBM 287, IBM 484, IBM 486), SCMAD 1.0 (Beta), SCBCD 1.3, ICSD (IBM 288), ICDBA (IBM 700, IBM 701), SCDJWS, ICSD (IBM 348), OCP 10g DBA (Beta), SCJP 5.0 (Beta), SCJA 1.0 (Beta), MCP(70-270), SCBCD 5.0 (Beta), SCJP 6.0, SCEA for JEE5 (in progress)
K Man
Greenhorn

Joined: Apr 15, 2004
Posts: 10
Hi Nicholas,
THanks for your reply. I will try what you said and post if I have any further questions.
Thanks,
-Krishna
K Man
Greenhorn

Joined: Apr 15, 2004
Posts: 10
Hi,
I am still having trouble with this. WHat i was trying to do is if I encounter a directory in the src, then I grab all of its files store it in a File array and then pass it recursively to mirrorFiles and it runs again. However, this doesnt seem to work. Any help would be appreciated. The code I have is this:
private final void mirrorFiles(File [] srcFiles, File trgFilesRoot, File [] trgFiles)
throws Exception,IOException
{
Map trgMap = this.asMap(trgFiles);
File src;
File trg;
for (int i=0; i<srcFiles.length; i++)
{
src = srcFiles[i];
trg = (File)trgMap.get(src.getName());
// TROUBLE AT THIS POINT! Trying to handle mirroring of directories
if(src.isDirectory() || (src.isDirectory() &&trg==null) || (src.isDirectory() && src.lastModified() != trg.lastModified()))
{
File []src2 = this.getFiles(src);
File []trg2 = this.getFiles(trg);
mirrorFiles(src2,trgFilesRoot,trg2);

}


else// If the src directory has something that trg doesnt have, then it's copied to trg.
{
if (!trgMap.containsKey(src.getName())) {
// 1 0
this.copy(src, new File(trgFilesRoot, src.getName()));
}

// If both src and trg have the same file then if the modification times of both files vary,
// then it is copied from src to trg since the file in src represents the latest version.
else {
// 1 1
trg = (File)trgMap.get(src.getName());
if (src.lastModified() != trg.lastModified()) {
this.copy(src, trg);
}
}
}
}
// If trg has something the src doesnt have, then it is wiped out.
Map srcMap = this.asMap(srcFiles);
for (int i=0; i<trgFiles.length; i++)
{
trg = trgFiles[i];
if (!srcMap.containsKey(trg.getName())) {
// 0 1
trg.delete();
}

}
}
Thanks,
-K Man
[ April 16, 2004: Message edited by: K Man ]
K Man
Greenhorn

Joined: Apr 15, 2004
Posts: 10
Can anybody point me in the right direction?
Thanks,
-Krishna
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
I did something like this in Pascal years ago. A couple thoughts ... if you can build your two lists of files in a sorted array or List or whatever, you can apply a more efficient algorithm to matching them up:

Now it will be much easier to expand your code to do something about files in B only or files with matching names but different dates. My Pascal program had 14 choices ... if A only, copy A to B or erase A; if B only copy from B to A or erase B; if A is newer, erase A, erase B, copy A to B, copy B to A, etc.
(Caveat - you'll have to figure out how to handle one list longer than the other. I added a bogus entry to the end of each list with an impossibly high name that would always be higher than a real file.)
Other thought: At what level do you want to do recursion? Say you had a routine that took two directory names as arguments and compared them. Then when you hit a directory the routine could call itself. In the methods suggested above - handleAOnly, handleBOnly and handleMatch - you could check for directories.

You'll have to give some thought to whether you want to make a new directory in B or not.
Any of that help?


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
K Man
Greenhorn

Joined: Apr 15, 2004
Posts: 10
Okay,
I am very close to getting this. THe mirroring algorithm seems to work for most cases except for one case. Suppose the trg has something (file or dir) that the src doesnt have. In this case, whatever stuff the trg has should be wiped out when the application RUns since it should have exactly what the src has. When my application runs for this case, it wipes out whatever the trg has but there is an exception. Suppose the src doesnt have some directories and the trg has these directories. it wipes out directories in the trg that dont have files, but it doesnt wipe out directories in the trg that have stuff in it (such as files or directories). How do I handle this case?
Thanks,
-K Man
K Man
Greenhorn

Joined: Apr 15, 2004
Posts: 10
Hi Stan,
Thanks for your post. I approached it in a complete different way I think so I would have to uproot all of my code to do it the way you were suggesting.
Thanks for the help though,
- K Man
K Man
Greenhorn

Joined: Apr 15, 2004
Posts: 10
Hi,
I "wrote" a method that removes directories with stuff in it. Praise the lord for creating the Java Almanac!
-K Man
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: A Mirroring Algorithm