Java: Using nio Files.copy to Move Directory - java

I am new to the nio class, and am having trouble moving a directory of files to a newly created directory.
I first create 2 directories with:
File sourceDir = new File(sourceDirStr); //this directory already exists
File destDir = new File(destDirectoryStr); //this is a new directory
I then try to copy the existing files into the new directory, using:
Path destPath = destDir.toPath();
for (int i = 0; i < sourceSize; i++) {
Path sourcePath = sourceDir.listFiles()[i].toPath();
Files.copy(sourcePath, destPath.resolve(sourcePath.getFileName()));
}
This throws the following error:
Exception in thread "main" java.nio.file.FileSystemException: destDir/Experiment.log: Not a directory
I know that destDir/Experiment.log is not an existing directory; it should be a new file as a result of the Files.copy operation. Could someone point out where my operation is going wrong? Thanks!

You need to use walkFileTree to copy directories. If you use Files.copy on a directory only an empty directory will be created.
Following code taken/adapted from http://codingjunkie.net/java-7-copy-move/
File src = new File("c:\\temp\\srctest");
File dest = new File("c:\\temp\\desttest");
Path srcPath = src.toPath();
Path destPath = dest.toPath();
Files.walkFileTree(srcPath, new CopyDirVisitor(srcPath, destPath, StandardCopyOption.REPLACE_EXISTING));
public static class CopyDirVisitor extends SimpleFileVisitor<Path>
{
private final Path fromPath;
private final Path toPath;
private final CopyOption copyOption;
public CopyDirVisitor(Path fromPath, Path toPath, CopyOption copyOption)
{
this.fromPath = fromPath;
this.toPath = toPath;
this.copyOption = copyOption;
}
#Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException
{
Path targetPath = toPath.resolve(fromPath.relativize(dir));
if( !Files.exists(targetPath) )
{
Files.createDirectory(targetPath);
}
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
{
Files.copy(file, toPath.resolve(fromPath.relativize(file)), copyOption);
return FileVisitResult.CONTINUE;
}
}

Simply make the destination directory if it doesn't exist.
File sourceDir = new File(source); //this directory already exists
File destDir = new File(dest); //this is a new directory
destDir.mkdirs(); // make sure that the dest directory exists
Path destPath = destDir.toPath();
for (File sourceFile : sourceDir.listFiles()) {
Path sourcePath = sourceFile.toPath();
Files.copy(sourcePath, destPath.resolve(sourcePath.getFileName()));
}
Note that sourceDir.listFiles() will also return directories, which you will either want t recurse into, or ignore...

This is my solution for recursively moving a directory from source to target. It works like a charm.
public static void move(Path source, Path target) throws IOException {
class FileMover extends SimpleFileVisitor<Path> {
private Path source;
private Path target;
private FileMover(Path source, Path target) {
this.source = source;
this.target = target;
}
#Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
Files.move(file, target.resolve(source.relativize(file)),
StandardCopyOption.REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
Path newDir = target.resolve(source.relativize(dir));
try {
Files.copy(dir, newDir,
StandardCopyOption.COPY_ATTRIBUTES,
StandardCopyOption.REPLACE_EXISTING);
} catch (DirectoryNotEmptyException e) {
// ignore and skip
}
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
Path newDir = target.resolve(source.relativize(dir));
FileTime time = Files.getLastModifiedTime(dir);
Files.setLastModifiedTime(newDir, time);
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
}
FileMover fm = new FileMover(source, target);
EnumSet<FileVisitOption> opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
Files.walkFileTree(source, opts, Integer.MAX_VALUE, fm);
}

for (int i = 0; i < sourceSize; i++) {
Path sourcePath = sourceDir.listFiles()[i].toPath();
Files.copy(sourcePath, destPath.resolve(sourcePath.getFileName()));
}
This is very strange code. You have already got a file count from somewhere, in sourceSize, yet you are calling listFiles() for every iteration. I would have expected something more like this:
for (File file : sourceDir.listFiles()) {
Path sourcePath = file.toPath();
Files.copy(sourcePath, destPath.resolve(sourcePath.getFileName()));
}

Related

How to copy resources folder out of jar into program files

I have spent hours and hours searching for the answer and I just can't figure it out, I am trying to copy my resources folder which contains all the images and data files for my game I am working on out of the running jar and into
E:/Program Files/mtd/ It works fine when I run it out of eclipse, but when I export the jar and try it, I get NoSuchFileException
`JAR
Installing...
file:///C:/Users/Cam/Desktop/mtd.jar/resources to file:///E:/Program%20Files/mtd
/resources
java.nio.file.NoSuchFileException: C:\Users\Cam\Desktop\mtd.jar\resources
at sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.WindowsFileAttributeViews$Basic.readAttributes(Unknown Sou
rce)
at sun.nio.fs.WindowsFileAttributeViews$Basic.readAttributes(Unknown Sou
rce)
at sun.nio.fs.WindowsFileSystemProvider.readAttributes(Unknown Source)
at java.nio.file.Files.readAttributes(Unknown Source)
at java.nio.file.FileTreeWalker.walk(Unknown Source)
at java.nio.file.FileTreeWalker.walk(Unknown Source)
at java.nio.file.Files.walkFileTree(Unknown Source)
at java.nio.file.Files.walkFileTree(Unknown Source)
at me.Zacx.mtd.main.Game.<init>(Game.java:94)
at me.Zacx.mtd.main.Game.main(Game.java:301)`
This is the code I am using:
if (!pfFolder.exists()) {
pfFolder.mkdir();
try {
URL url = getClass().getResource("/resources/");
URI uri = null;
if (url.getProtocol().equals("jar")) {
System.out.println("JAR");
JarURLConnection connect = (JarURLConnection) url.openConnection();
uri = new URI(connect.getJarFileURL().toURI().toString() + "/resources/");
} else if (url.getProtocol().equals("file")) {
System.out.println("FILE");
uri = url.toURI();
}
final Path src = Paths.get(uri);
final Path tar = Paths.get(System.getenv("ProgramFiles") + "/mtd/resources/");
System.out.println("Installing...");
System.out.println(src.toUri() + " to " + tar.toUri());
Files.walkFileTree(src, new SimpleFileVisitor<Path>() {
public FileVisitResult visitFile( Path file, BasicFileAttributes attrs ) throws IOException {
return copy(file);
}
public FileVisitResult preVisitDirectory( Path dir, BasicFileAttributes attrs ) throws IOException {
return copy(dir);
}
private FileVisitResult copy( Path fileOrDir ) throws IOException {
System.out.println("Copying " + fileOrDir.toUri() + " to " + tar.resolve( src.relativize( fileOrDir ) ).toUri());
Files.copy( fileOrDir, tar.resolve( src.relativize( fileOrDir ) ) );
return FileVisitResult.CONTINUE;
}
});
System.out.println("Done!");
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
This was harder that I thought, but here is how to do it.
here is my copy method Reference https://examples.javacodegeeks.com/core-java/io/file/4-ways-to-copy-file-in-java/
public void copyFile(String inputPath, String outputPath ) throws IOException
{
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = getClass().getResourceAsStream(inputPath);
outputStream = new FileOutputStream(outputPath);
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, bytesRead);
}
}
finally {
inputStream.close();
outputStream.close();
}
Please note the structure of the project of the Jar file in this image Project structure
Now I need to read the Jar file. This is a varition on this solution How can I get a resource "Folder" from inside my jar File? . Both of these methods work together to product the result. I have tested this and it works.
public class Main {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
final String pathPartOne = "test/com";
final String pathPartTwo = "/MyResources";
String pathName = "C:\\Users\\Jonathan\\Desktop\\test.jar";
JarTest test = new JarTest();
final File jarFile = new File(pathName);
if(jarFile.isFile()) { // Run with JAR file
final JarFile jar = new JarFile(jarFile);
final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
while(entries.hasMoreElements()) {
final String name = entries.nextElement().getName();
if (name.startsWith(pathPartOne+pathPartTwo + "/")) { //filter according to the path
if(name.contains("."))//has extension
{
String relavtivePath = name.substring(pathPartOne.length()+1);
String fileName = name.substring(name.lastIndexOf('/')+1);
System.out.println(relavtivePath);
System.out.println(fileName);
test.copyFile(relavtivePath, "C:\\Users\\Jonathan\\Desktop\\" + fileName);
}
}
}
jar.close();
}
}
}
Hope that helps.
The problem here is different File Systems. C:/Users/Cam/Desktop/mtd.jar is a File in the WindowsFileSystem. Since it is a file, and not a directory, you cannot access a subdirectory inside the file; C:/Users/Cam/Desktop/mtd.jar/resources is only a valid Path if mtd.jar is actually a directory instead of a file.
In order to access something on a different file system, you must use the path from the root of that file system. For example, if you have a file in D:\dir1\dir2\file, you cannot reach it using a path that begins with C:\ (symbolic links not withstanding); you must use a path that starts at the root of that file system D:\.
A jar file is just a file. It can be located anywhere within a file system, and can be moved, copied or deleted like any regular file. However, it contains within itself its own file system. There is no windows path that can be used to reference any file inside the jar's file system, just like no path starting at C:\ can reference any file within the D:\ file system.
In order to access the contents of a jar, you must open the jar as a ZipFileSystem.
// Autoclose the file system at end of try { ... } block.
try(FileSystem zip_fs = FileSystems.newFileSystem(pathToZipFile, null)) {
}
Once you have zip_fs, you can use zip_fs.getPath("/path/in/zip"); to get a Path to a file within it. This Path object will actually be a ZipFileSystemProvider path object, not a WindowsFileSystemProvider path object, but otherwise it is a Path object that can be opened, read from, etc., at least until the ZipFileSystem is closed. The biggest differences are that path.getFileSystem() will return the ZipFileSystem, and that resolve() and relativize() cannot use path objects where getFileSystem() returns different file systems.
When your project ran from Eclipse, all the resources were in the WindowsFileSystem, so walking the file system tree and copying the resources was straight forward. When your project ran from a jar, the resources were not in the default file system.
Here is a Java class that will copy resources to an installation directory. It will work in Eclipse (with all the resources as individual files), as well as when the application is packaged into a jar.
public class Installer extends SimpleFileVisitor<Path> {
public static void installResources(Path dst, Class<?> cls, String root) throws URISyntaxException, IOException {
URL location = cls.getProtectionDomain().getCodeSource().getLocation();
if (location.getProtocol().equals("file")) {
Path path = Paths.get(location.toURI());
if (location.getPath().endsWith(".jar")) {
try (FileSystem fs = FileSystems.newFileSystem(path, null)) {
installResources(dst, fs.getPath("/" + root));
}
} else {
installResources(dst, path.resolve(root));
}
} else {
throw new IllegalArgumentException("Not supported: " + location);
}
}
private static void installResources(Path dst, Path src) throws IOException {
Files.walkFileTree(src, new Installer(dst, src));
}
private final Path target, source;
private Installer(Path dst, Path src) {
target = dst;
source = src;
}
private Path resolve(Path path) {
return target.resolve(source.relativize(path).toString());
}
#Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
Path dst = resolve(dir);
Files.createDirectories(dst);
return super.preVisitDirectory(dir, attrs);
}
#Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path dst = resolve(file);
Files.copy(Files.newInputStream(file), dst, StandardCopyOption.REPLACE_EXISTING);
return super.visitFile(file, attrs);
}
}
Called as:
Path dst = Paths.get("C:\\Program Files\\mtd");
Installer.installResources(dst, Game.class, "resources");
I FINALLY FOUND THE ANSWER
I don't want to type out a big, long explanation but for anyone looking for the solution, here it is
`
//on startup
installDir("");
for (int i = 0; i < toInstall.size(); i++) {
File f = toInstall.get(i);
String deepPath = f.getPath().replace(f.getPath().substring(0, f.getPath().lastIndexOf("resources") + "resources".length() + 1), "");
System.out.println(deepPath);
System.out.println("INSTALLING: " + deepPath);
installDir(deepPath);
System.out.println("INDEX: " + i);
}
public void installDir(String path) {
System.out.println(path);
final URL url = getClass().getResource("/resources/" + path);
if (url != null) {
try {
final File apps = new File(url.toURI());
for (File app : apps.listFiles()) {
System.out.println(app);
System.out.println("copying..." + app.getPath() + " to " + pfFolder.getPath());
String deepPath = app.getPath().replace(app.getPath().substring(0, app.getPath().lastIndexOf("resources") + "resources".length() + 1), "");
System.out.println(deepPath);
try {
File f = new File(resources.getPath() + "/" + deepPath);
if (getExtention(app) != null) {
FileOutputStream resourceOS = new FileOutputStream(f);
byte[] byteArray = new byte[1024];
int i;
InputStream classIS = getClass().getClassLoader().getResourceAsStream("resources/" + deepPath);
//While the input stream has bytes
while ((i = classIS.read(byteArray)) > 0)
{
//Write the bytes to the output stream
resourceOS.write(byteArray, 0, i);
}
//Close streams to prevent errors
classIS.close();
resourceOS.close();
} else {
System.out.println("new dir: " + f.getPath() + " (" + toInstall.size() + ")");
f.mkdir();
toInstall.add(f);
System.out.println(toInstall.size());
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (URISyntaxException ex) {
// never happens
}
}
}`

How to pass String value (filepath) dynamically in file class?

String filepath=null;
public void dirScan()
{
File root = new File("/tmp/");
FilenameFilter beginswithm = new FilenameFilter()
{
public boolean accept(File directory, String filename) {
return filename.startsWith("201");
}
};
File[] files = root.listFiles(beginswithm);
for (File f: files)
{
filepath=f.toString();
System.out.println(filepath);
}
}
public void prepDownload() throws Exception {
File file = new File(filepath);
FileInputStream input = new FileInputStream(file);
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
setDownload(new DefaultStreamedContent(input, externalContext.getMimeType(file.getName()), file.getName()));
System.out.println("PREP = " + download.getName());
}
public DefaultStreamedContent getDownload() throws Exception {
System.out.println("GET = " + download.getName());
return download;
}
I have a tmp folder in my system. This folder having some dynamic generated files. I want to pass filepath as dynamically preDownload() method. But in my method only last value of filepath is passed to preDownlaod method. while accessing getDownload method it fetches last filepath value. I want to download file from generated rows.Each row having unique file but in my case all rows having same file .
Any help or suggestion will be appreciated. Thanks in advance.
Do you mean that for each file found that matches your filter you want to pass to prepDownload() ? If so then you can try making the following changes:
...
for (File f: files){
filepath=f.toString();
prepDownload(filepath);
}
...
public void prepDownload(String filePath) throws Exception {
...
}
This will guarantee that as each file is found you will call prepDownload.
Alternative Approach:
Use a set to keep track of things instead. I.e.:
Set<String> filepaths = new HashSet<String>();
public void dirScan(){
...
File[] files = root.listFiles(beginswithm);
for (File f: files)
{
filepath=f.toString();
filepaths.add(filepath);
}
}
public void prepDownload() throws Exception {
for(String filepath: filepaths){
File file = new File(filepath);
....
}
}

display path of all files in the folder relative to the first file encountered in that folder

I am new to Java, I tried to practice some example but I am facing issue in the file handling topic.
Following is the example that what I am trying.
T1--> T2--> T3--> T4--> Gan--> q.txt
|
--> Lin-->Img-->s.png
|
--> p.txt
This is the folder structure.
And I want output in the following format.
p.txt
Lin/Img/s.png
Gen/q.txt
That means when the first file is getting in any directory, after that next file will be printed with the path from first file is got.
The above directory structure is not fixed. It may change.
Now following are code that I have did but I am not getting proper output:
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
class FileProgram {
private ArrayList<File> listOfDirectories = new ArrayList<File>();
private ArrayList<File> rawFiles = new ArrayList<File>();
private ArrayList<String> parentDir = new ArrayList<String>();
private ArrayList<String> filesToDisplay = new ArrayList<String>();
private Iterator i, listDir;
private boolean firstFile = false;
private String parents = "";
public void getDetails(File file) {
try {
if (file.exists()) {
File directoies[] = file.listFiles();
if (!rawFiles.isEmpty()) {
rawFiles.clear();
}
for (File f : directoies) {
rawFiles.add(f);
}
i = rawFiles.iterator();
while (i.hasNext()) {
File isFile = (File) i.next();
if (isFile.isFile()) {
displayFiles(isFile);
}
if (isFile.isDirectory()) {
listOfDirectories.add(isFile);
}
}
iterateInnerDirectories();
} else {
System.out.println("Invalid File Path");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
FileProgram ray = new FileProgram();
ray.getDetails(new File("D:\\Temp"));
}
private void iterateInnerDirectories() {
listDir = listOfDirectories.iterator();
while (listDir.hasNext()) {
File isFile = (File) listDir.next();
File f = isFile;
listOfDirectories.remove(isFile);
getDetails(isFile);
}
}
private void displayFiles(File file) {
if (firstFile == false) {
firstFile = true;
String rootPath = file.getParent();
rootPath = rootPath.replace(file.getName(), "");
parentDir.add(rootPath);
parents = file.getParentFile().getName();
System.out.println(file.getName());
filesToDisplay.add(file.getName());
} else {
String rootPath = file.getParent();
rootPath = rootPath.replace(file.getName(), "");
if (parentDir.contains(rootPath)) {
parents = file.getParentFile().getName();
System.out.println(file.getName());
filesToDisplay.add(file.getName());
} else {
System.out.println(file);
}
}
}
}
Please anybody can help me to get proper output that I have mentioned above.
Thanks in advance.
Unless you're using a Java prior to Java 7 I would strongly suggest to use Path.
You can walk a directory recursively using Files.walkFileTree().
Once you encounter a file (!Files.isDirectory()), you can get its parent with Path.getParent(). And you can print the relative path to this parent of all further file using Path.relativize().
Short, Simple Implementation
In this implementation I don't even use Files.isDirectory() because visitFile() is only called for files:
public static void printFiles(Path start) {
try {
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
Path parent;
#Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
if (parent == null)
parent = file.getParent();
System.out.println(parent.relativize(file));
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
And this is how you call it:
printFiles(Paths.get("/path/to/T1"));

get file names by directory and sub directory

i need to get all file names by giving a directory and sub directories
from some reason it doesn't work and i have no idea what is the problem
this is what i did:
import java.io.File;
public class Main
{
public static void main(String[] args) {
String root = "C:\\eclipse";// root directory
String[] filename = null;
filename = getFfileNamesAndInsertToArray(root, filename);
printFileNames(filename);
}
public static void printFileNames(String[] filenames) {
for (int i = 0; i < filenames.length; i++) {
System.out.println(filenames[i]);
}
}
public static String[] getFfileNamesAndInsertToArray(String root, String[] filenames) {
String[] files = filenames;
java.io.File dir = new java.io.File(root);
for (java.io.File file : dir.listFiles()) {
// String path = file.getAbsolutePath(); // get path of file
if (file.isDirectory() == false) {
files[files.length + 1] = file.getName();
}
else {
root = file.getAbsolutePath();
getFfileNamesAndInsertToArray(root, files);
}
}
return files;
}
}
You don't have to do this by hand. You can use Files.walkFileTree for this
Path path = Paths.get("your/directory/path");
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
#Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
// this is called for each file
}
});
You have to initialise any array with a specific size like:
String[] files = new String[20];
So if you don't know the size in particular (like in your case), you could use an ArrayList.
If you do not initialise your string-array and want to save a string at position length+1, your program will fail since your array has no length at that point. And it does not dynamically allocate new memory, hence it cannot grow and get larger.
If you use an ArrayList of type String you cann call the arraylist.add-method to add new Elements and the list gets appended everytime, so you don't have to worry about it's size.
Could do something like this:
public static List<String> getListOfFiles(String root) throws IOException {
final List<String> fileNames = new ArrayList<>();
Files.walkFileTree(Paths.get(root), new SimpleFileVisitor<Path>() {
#Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (attrs.isRegularFile()) {
fileNames.add(file.getFileName().toString());
}
return super.visitFile(file, attrs);
}
});
return fileNames;
}

How to copy all files with certain extensions from a directory and sub directories?

I know how to copy a file from one directory to another, what I would like help on is copy a file with .jpg or .doc extension.
So for example.
Copy all files from D:/Pictures/Holidays
Scanning all folders in the above path and transfer all jpg's to a destination provided.
This works, but the file 'copy(File file, File outputFolder)' method could be enhanced for large files:
package net.bpfurtado.copyfiles;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class CopyFilesFromType
{
public static void main(String[] args)
{
new CopyFilesFromType().copy("jpg", "C:\\Users\\BrunoFurtado\\Pictures", "c:/temp/photos");
}
private FileTypeOrFolderFilter filter = null;
private void copy(final String fileType, String fromPath, String outputPath)
{
filter = new FileTypeOrFolderFilter(fileType);
File currentFolder = new File(fromPath);
File outputFolder = new File(outputPath);
scanFolder(fileType, currentFolder, outputFolder);
}
private void scanFolder(final String fileType, File currentFolder, File outputFolder)
{
System.out.println("Scanning folder [" + currentFolder + "]...");
File[] files = currentFolder.listFiles(filter);
for (File file : files) {
if (file.isDirectory()) {
scanFolder(fileType, file, outputFolder);
} else {
copy(file, outputFolder);
}
}
}
private void copy(File file, File outputFolder)
{
try {
System.out.println("\tCopying [" + file + "] to folder [" + outputFolder + "]...");
InputStream input = new FileInputStream(file);
OutputStream out = new FileOutputStream(new File(outputFolder + File.separator + file.getName()));
byte data[] = new byte[input.available()];
input.read(data);
out.write(data);
out.flush();
out.close();
input.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private final class FileTypeOrFolderFilter implements FileFilter
{
private final String fileType;
private FileTypeOrFolderFilter(String fileType)
{
this.fileType = fileType;
}
public boolean accept(File pathname)
{
return pathname.getName().endsWith("." + fileType) || pathname.isDirectory();
}
}
}
Use a FileFilter when listing files.
In this case, the filter would select directories and any file type of interest.
Here is a quick example (crudely hacked out of another project) of gaining a list of types of files in a directory structure.
import java.io.*;
import java.util.ArrayList;
class ListFiles {
public static void populateFiles(File file, ArrayList<File> files, FileFilter filter) {
File[] all = file.listFiles(filter);
for (File f : all) {
if (f.isDirectory()) {
populateFiles(f,files,filter);
} else {
files.add(f);
}
}
}
public static void main(String[] args) throws Exception {
String[] types = {
"java",
"class"
};
FileFilter filter = new FileTypesFilter(types);
File f = new File("..");
ArrayList<File> files = new ArrayList<File>();
populateFiles(f, files, filter);
for (File file : files) {
System.out.println(file);
}
}
}
class FileTypesFilter implements FileFilter {
String[] types;
FileTypesFilter(String[] types) {
this.types = types;
}
public boolean accept(File f) {
if (f.isDirectory()) return true;
for (String type : types) {
if (f.getName().endsWith(type)) return true;
}
return false;
}
}
Use following file walker tree class to do that
static class TreeCopier implements FileVisitor<Path> {
private final Path source;
private final Path target;
private final boolean preserve;
private String []fileTypes;
TreeCopier(Path source, Path target, boolean preserve, String []types) {
this.source = source;
this.target = target;
this.preserve = preserve;
this.fileTypes = types;
}
#Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
// before visiting entries in a directory we copy the directory
// (okay if directory already exists).
CopyOption[] options = (preserve)
? new CopyOption[]{COPY_ATTRIBUTES} : new CopyOption[0];
Path newdir = target.resolve(source.relativize(dir));
try {
Files.copy(dir, newdir, options);
} catch (FileAlreadyExistsException x) {
// ignore
} catch (IOException x) {
System.err.format("Unable to create: %s: %s%n", newdir, x);
return SKIP_SUBTREE;
}
return CONTINUE;
}
#Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
String fileName = file.toFile().getName();
boolean correctType = false;
for(String t: fileTypes) {
if(fileName.endsWith(t)){
correctType = true;
break;
}
}
if(correctType)
copyFile(file, target.resolve(source.relativize(file)), preserve);
return CONTINUE;
}
#Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
// fix up modification time of directory when done
if (exc == null && preserve) {
Path newdir = target.resolve(source.relativize(dir));
try {
FileTime time = Files.getLastModifiedTime(dir);
Files.setLastModifiedTime(newdir, time);
} catch (IOException x) {
System.err.format("Unable to copy all attributes to: %s: %s%n", newdir, x);
}
}
return CONTINUE;
}
#Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
if (exc instanceof FileSystemLoopException) {
System.err.println("cycle detected: " + file);
} else {
System.err.format("Unable to copy: %s: %s%n", file, exc);
}
return CONTINUE;
}
static void copyFile(Path source, Path target, boolean preserve) {
CopyOption[] options = (preserve)
? new CopyOption[]{COPY_ATTRIBUTES, REPLACE_EXISTING}
: new CopyOption[]{REPLACE_EXISTING};
if (Files.notExists(target)) {
try {
Files.copy(source, target, options);
} catch (IOException x) {
System.err.format("Unable to copy: %s: %s%n", source, x);
}
}
}
}
and call it using following two lines
String []types = {".java", ".form"};
TreeCopier tc = new TreeCopier(src.toPath(), dest.toPath(), false, types);
Files.walkFileTree(src.toPath(), tc);
.java and .form file types are not omitted to copy and passed as String array parameter, src.toPath() and dest.toPath() are source and destination paths, false is used to specify not to preserve previous files and overwrite them
if you want reverse that is to consider only these remove not and use as
if(!correctType)
Take a look at the listFiles methods from the File class:
Link 1
Link 2
You could try this code:
public class MyFiler implements FileNameFilter{
bool accept(File file, String name){
if(name.matches("*.jpg");
}
}
public void MassCopy(){
ArrayList<File> filesToCopy = new ArrayList<File>();
File sourceDirectory = new File("D:/Pictures/Holidays");
String[] toCopy = sourceDirectory.list(new MyFilter());
for(String file : toCopy){
copyFileToDestination(file);
}
}

Categories