File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

A Mirroring Algorithm

 
K Man
Greenhorn
Posts: 10
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 4982
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
 
K Man
Greenhorn
Posts: 10
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 10
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 10
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can anybody point me in the right direction?
Thanks,
-Krishna
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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?
 
K Man
Greenhorn
Posts: 10
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 10
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 10
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,
I "wrote" a method that removes directories with stuff in it. Praise the lord for creating the Java Almanac!
-K Man
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic