i want to copy files from parent directory into subfolder in parent directory. Now i get the copied files into subfolder, but it repeated itself everytime if i get already the subfolder and files copied, it makes it all time repeatedly, i want it to male only one time
public static void main(String[] args) throws IOException {
File source = new File(path2);
File target = new File("Test/subfolder");
copyDirectory(source, target);
}
public static void copyDirectory(File sourceLocation, File targetLocation)
throws IOException {
if (sourceLocation.isDirectory()) {
if (!targetLocation.exists()) {
targetLocation.mkdir();
}
String[] children = sourceLocation.list();
for (int i = 0; i < children.length; i++) {
copyDirectory(new File(sourceLocation, children[i]), new File(
targetLocation, children[i]));
}
} else {
InputStream in = new FileInputStream(sourceLocation);
OutputStream out = new FileOutputStream(targetLocation);
byte[] buf = new byte[1];
int length;
while ((length = in.read(buf)) > 0) {
out.write(buf, 0, length);
}
in.close();
out.close();
}
}
You program have problem in following line
String[] children = sourceLocation.list();
Lets suppose your parent dir = Test
So the following code will create a sub-folder under test
if (!targetLocation.exists()) {
targetLocation.mkdir();
}
And after that you are retrieving the children of source folder as your destination is already created it will also be counted as child of source folder and recursively get copied. So you need to retrieve children first and then create the target directory So that target directory would not be count in copy process.
Change your code as follows.
public static void main(String[] args) throws IOException {
File source = new File("Test");
File target = new File("Test/subfolder");
copyDirectory(source, target);
}
public static void copyDirectory(File sourceLocation, File targetLocation)
throws IOException {
String[] children = sourceLocation.list();
if (sourceLocation.isDirectory()) {
if (!targetLocation.exists()) {
targetLocation.mkdir();
}
for (int i = 0; i < children.length; i++) {
copyDirectory(new File(sourceLocation, children[i]), new File(
targetLocation, children[i]));
}
} else {
InputStream in = new FileInputStream(sourceLocation);
OutputStream out = new FileOutputStream(targetLocation);
byte[] buf = new byte[1];
int length;
while ((length = in.read(buf)) > 0) {
out.write(buf, 0, length);
}
in.close();
out.close();
}
}
You are calling your method recursively without a condition to break the recursion. You will have to exclude directories in your for-loop.
Related
I have a directory with sub-directories which contains text or binary files ( like pictures ). I need to find duplicate files which can be in different sub-directories and with different names. So, I need to use some algorithm which would look inside the files and NOT rely on file name, or length of file.
I could come up with a quick solution. I know this code can be written much better but functionality wise its working perfect. I even tested it on jpeg, gif files.
public static Map<String, List<File>> mapFilesHash = new HashMap<String, List<File>>();
public static MessageDigest md ;
static {
try {
md = MessageDigest.getInstance("MD5");
} catch (Exception ex) {}
}
private static String checksum(File file) throws IOException {
FileInputStream fis = new FileInputStream(file);
byte[] byteArray = new byte[1024];
int bytesCount = 0;
while ((bytesCount = fis.read(byteArray)) != -1) {
md.update(byteArray, 0, bytesCount);
}
fis.close();
byte[] bytes = md.digest();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
public static void findDuplicateFiles(File rootDir) throws Exception {
iterateOverDirectory(rootDir);
System.out.println("based on hash "+mapFilesHash.size());
for (List<File> files: mapFilesHash.values()) {
if (files.size() > 1 ) {
System.out.println(files);
}
}
}
private static void iterateOverDirectory (File rootDir) throws Exception {
for (File file : rootDir.listFiles()) {
if (file.isDirectory()) {
iterateOverDirectory(file);
} else {
if (mapFilesSize.get(file.length()) == null) {
mapFilesSize.put(file.length(), new ArrayList<>());
}
mapFilesSize.get(file.length()).add(file);
String md5hash = checksum(file);
if (mapFilesHash.get(md5hash) == null) {
mapFilesHash.put(md5hash, new ArrayList<>());
}
mapFilesHash.get(md5hash).add(file);
}
}
}
Without mapFilesSize your method iterateOverDirectory can became:
private static void iterateOverDirectory(File rootDir) throws Exception {
for (File file : rootDir.listFiles()) {
if (file.isDirectory()) {
iterateOverDirectory(file);
}
else {
mapFilesHash.computeIfAbsent(checksum(file), k -> new ArrayList<>()).add(file);
}
}
}
I am trying to write a program which will delete all duplicate files in a directory. It is currently able to detect duplicates, but my deleting code does not seem to be working (Files.delete() returns false). Can anybody tell me why this is?
Current code:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.SecurityManager;
public class Duplicate {
#SuppressWarnings("resource")
public static boolean isDuplicate(File a, File b) throws IOException {
FileInputStream as = new FileInputStream(a);
FileInputStream bs = new FileInputStream(b);
while(true) {
int aBytes = as.read();
int bBytes = bs.read();
if(aBytes != bBytes) {
return false;
} else if(aBytes == -1) {
System.out.println("Duplicate found: "+a.getName()+", "+b.getName());
return true;
}
}
}
public static void main(String[] args) throws IOException {
File dir = new File(System.getProperty("user.dir"));
File[] files = dir.listFiles();
for(int i = 0; i < files.length; i++) {
for(int j = i+1; j < files.length; j++) {
if(isDuplicate(files[i], files[j])) {
String filePath = System.getProperty("user.dir").replace("\\", "/")+"/"+files[i].getName();
System.out.println("Deleting "+filePath);
File f = new File(filePath);
if(f.delete())
System.out.println(filePath+" deleted successfully");
else
System.out.println("Could not delete "+filePath);
}
}
}
}
}
Did you close your file streams? It would make sense that it would return false if the file is currently open.
Apart from the resources problem (which certainly explains why you can't delete), the problem is that you won't know why the deletion fails -- in fact, with File you have no means to know at all.
Here is the equivalent program written with java.nio.file, with resource management:
public final class Duplicates
{
private Duplicates()
{
throw new Error("nice try!");
}
private static boolean duplicate(final Path path1, final Path path2)
throws IOException
{
if (Files.isSameFile(path1, path2))
return true;
final BasicFileAttributeView view1
= Files.getFileAttributeView(path1, BasicFileAttributeView.class);
final BasicFileAttributeView view2
= Files.getFileAttributeView(path2, BasicFileAttributeView.class);
final long size1 = view1.readAttributes().size();
final long size2 = view2.readAttributes().size();
if (size1 != size2)
return false;
try (
final FileChannel channel1 = FileChannel.open(path1,
StandardOpenOption.READ);
final FileChannel channel2 = FileChannel.open(path2,
StandardOpenOption.READ);
) {
final ByteBuffer buf1
= channel1.map(FileChannel.MapMode.READ_ONLY, 0L, size1);
final ByteBuffer buf2
= channel2.map(FileChannel.MapMode.READ_ONLY, 0L, size1);
// Yes, this works; see javadoc for ByteBuffer.equals()
return buf1.equals(buf2);
}
}
public static void main(final String... args)
throws IOException
{
final Path dir = Paths.get(System.getProperty("user.dir"));
final List<Path> list = new ArrayList<>();
for (final Path entry: Files.newDirectoryStream(dir))
if (Files.isRegularFile(entry))
list.add(entry);
final int size = list.size();
for (int i = 0; i < size; i++)
for (int j = i + 1; j < size; j++)
try {
if (duplicate(list.get(i), list.get(j)))
Files.deleteIfExists(list.get(j));
} catch (IOException e) {
System.out.printf("Aiie... Failed to delete %s\nCause:\n%s\n",
list.get(j), e);
}
}
}
Note: a better strategy would probably be to create a directory in which you will move all duplicates you detect; when done, just delete all files in this directory then the directory itself. See Files.move().
I want copy entire directory onClick in android.. How can i do it?
I have:
String sdCard = Environment.getExternalStorageDirectory().toString();
File srcFolder = new File(sdCard +"tryFirstFolder");
File destFolder = new File(sdCard +"/TryFolder");
And then i need the code to copy the entire content of srcFolder to destFolder
you can copy directory from one location to other using this:
public static void copyDirectoryOneLocationToAnotherLocation(File sourceLocation, File targetLocation)
throws IOException {
if (sourceLocation.isDirectory()) {
if (!targetLocation.exists()) {
targetLocation.mkdir();
}
String[] children = sourceLocation.list();
for (int i = 0; i < sourceLocation.listFiles().length; i++) {
copyDirectoryOneLocationToAnotherLocation(new File(sourceLocation, children[i]),
new File(targetLocation, children[i]));
}
} else {
InputStream in = new FileInputStream(sourceLocation);
OutputStream out = new FileOutputStream(targetLocation);
// Copy the bits from instream to outstream
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
}
also this link will help you to copy or move files from one folder to other:
http://www.codeofaninja.com/2013/04/copy-or-move-file-from-one-directory-to.html
I have a routine which i've been using for a while to copy a directory from an SD card to a plugged in USB drive. It works, but as there can be 3000 photos, i'm sure you get that it an get a bit slow. So i'm trying to implement some sort of update progress bar.
Here is my code that does the copying;
public void copyDirectory(File sourceLocation , File targetLocation)
throws IOException {
Log.e("Backup", "Starting backup");
if (sourceLocation.isDirectory()) {
if (!targetLocation.exists() && !targetLocation.mkdirs()) {
throw new IOException("Cannot create dir " + targetLocation.getAbsolutePath());
}
String[] children = sourceLocation.list();
for (int i=0; i<children.length; i++) {
copyDirectory(new File(sourceLocation, children[i]),
new File(targetLocation, children[i]));
}
} else {
Log.e("Backup", "Creating backup directory");
File directory = targetLocation.getParentFile();
if (directory != null && !directory.exists() && !directory.mkdirs()) {
throw new IOException("Cannot create dir " + directory.getAbsolutePath());
}
InputStream in = new FileInputStream(sourceLocation);
OutputStream out = new FileOutputStream(targetLocation);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
Log.e("Backup", "Finished");
}
}
I assume that I need to check how big the directory is before starting so i've added:
public static int CountFilesInDirectory(String location) {
File f = new File(location);
int count = 0;
for (File file : f.listFiles()) {
if (file.isFile()) {
count++;
}
}
return count;
}
But I guess, I can't work out how to put A and B together. I can't work out how to increment in the right place for the update. - I could be on the completely wrong path! Any tips really would be appreciated.
http://labs.makemachine.net/2010/05/android-asynctask-example/
see the above link async task loading concept will help you
I'm using the following code to create a backup of a folder structure on my app (backing up to remote USB)
It works fine, however now i'm trying to work out how to give an indication of how the current percentage of how it's going etc. Realistically, I guess I don't understand how the copy works enough to list how many files there are in the folders to work out a percentage? Or what to increment.
Any tips really will be appreciated.
Here is my backup code:
public void doBackup(View view) throws IOException{
Time today = new Time(Time.getCurrentTimezone());
today.setToNow();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
final String curDate = sdf.format(new Date());
final ProgressDialog pd = new ProgressDialog(this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Running backup. Do not unplug drive");
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.show();
Thread mThread = new Thread() {
#Override
public void run() {
File source = new File(Global.SDcard);
File dest = new File(Global.BackupDir + curDate);
try {
copyDirectory(source, dest);
} catch (IOException e) {
e.printStackTrace();
}
pd.dismiss();
}
};
mThread.start();
}
public void copyDirectory(File sourceLocation , File targetLocation)
throws IOException {
Log.e("Backup", "Starting backup");
if (sourceLocation.isDirectory()) {
if (!targetLocation.exists() && !targetLocation.mkdirs()) {
throw new IOException("Cannot create dir " + targetLocation.getAbsolutePath());
}
String[] children = sourceLocation.list();
for (int i=0; i<children.length; i++) {
copyDirectory(new File(sourceLocation, children[i]),
new File(targetLocation, children[i]));
}
} else {
Log.e("Backup", "Creating backup directory");
File directory = targetLocation.getParentFile();
if (directory != null && !directory.exists() && !directory.mkdirs()) {
throw new IOException("Cannot create dir " + directory.getAbsolutePath());
}
InputStream in = new FileInputStream(sourceLocation);
OutputStream out = new FileOutputStream(targetLocation);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
Log.e("Backup", "Finished");
}
}
You could call the following function on the top-most File to get the total size its contents...
long getFileSize(File aFile) {
//Function passed a single file, return the file's length.
if(!aFile.isDirectory())
return aFile.length();
//Function passed a directory.
// Sum and return the size of the directory's contents, including subfolders.
long netSize = 0;
File[] files = aFile.listFiles();
for (File f : files) {
if (f.isDirectory())
netSize += getFileSize(f);
else
netSize += f.length();
}
return netSize;
}
and then keep track of the total size of the files which have been copied. Using SizeOfCopiedFiles/SizeOfDirectory should give you a rough progress estimate.
Edit: Updating the progress bar...
The following loop seems like a good place to do updates...
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
sizeOfCopiedFiles += len;
pd.setProgress((float)SizeOfCopiedFiles/SizeOfDirectory);
}
(Note, I'm assuming there is pd.setProgress(float f) that takes a value from 0 to 1.)
To do this your copyDirectory(...) would need to take in a reference to your ProgressDialog, it would also need to take SizeOfCopiedFiles (for the sum of file writes from previous calls) and SizeOfDirectory. The function would need to return an updated value for sizeOfCopiedFiles to reflect the updated value after each recursive call.
In the end, you'd have something like this... (Note: Pseudocode for clarity)
public long copyDirectory(File source, File target, long sizeOfCopiedFiles,
long sizeOfDirectory, ProgressDialog pd) {
if (source.isDirectory()) {
for (int i = 0; i < children.length; i++) {
sizeOfCopiedFiles = copyDirectory(sourceChild, destChild,
sizeOfCopiedFiles, sizeOfDirectory, pd);
}
} else {
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
sizeOfCopiedFiles += len;
pd.setProgress((float)sizeOfCopiedFiles / sizeOfDirectory);
}
}
return sizeOfCopiedFiles;
}