I have the directory path being passed as an argument in Java program and the directory has various types of files. I want to retrieve path of text files and then further each text file.
I am new to Java, any recommendation how to go about it?
Even though this is not an optimum solution you can use this as a starting point.
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DirectoryWalker {
/**
* #param args
*/
private String extPtr = "^.+\\.txt$";
private Pattern ptr;
public DirectoryWalker(){
ptr = Pattern.compile(extPtr);
}
public static void main(String[] args) {
String entryPoint = "c:\\temp";
DirectoryWalker dw = new DirectoryWalker();
List<String> textFiles = dw.extractFiles(entryPoint);
for(String txtFile : textFiles){
System.out.println("File: "+txtFile);
}
}
public List<String> extractFiles(String startDir) {
List<String> textFiles = new ArrayList<String>();
if (startDir == null || startDir.length() == 0) {
throw new RuntimeException("Directory entry can't be null or empty");
}
File f = new File(startDir);
if (!f.isDirectory()) {
throw new RuntimeException("Path " + startDir + " is invalid");
}
File[] files = f.listFiles();
for (File tmpFile : files) {
if (tmpFile.isDirectory()) {
textFiles.addAll(extractFiles(tmpFile.getAbsolutePath()));
} else {
String path = tmpFile.getAbsolutePath();
Matcher matcher = ptr.matcher(path);
if(matcher.find()){
textFiles.add(path);
}
}
}
return textFiles;
}
}
Create a File object representing the directory, then use one of the list() or listFiles() methods to obtain the children. You can pass a filter to these to control what is returned.
For example, the listFiles() method below will return an array of files in the directory accepted by a filter.
public File[] listFiles(FileFilter filter)
Start by reading the File API. You can create a File from a String and even determine if it exists() or isDirectory(). As well as listing the children in that directory.
Related
I have a problem, i have this directory with 1k+ files and some folders. I need find the path of the files(which are in subdirectories) that starts with "BCM", but not only the first i find but every single file which start with that.
I tried looking at other answers about this topic but i couldn't find help,
tried using this code:
File dir = new File("K:\\Jgencs");
FilenameFilter filter = new FilenameFilter()
{
public boolean accept (File dir, String name)
{
return name.startsWith("BCM");
}
};
String[] children = dir.list(filter);
if (children == null)
{
System.out.println("No directory found");
}
else
{
for (int i = 0; i< children.length; i++)
{
String filename = children[i];
System.out.println(filename);
File h = new File(dir,filename);
System.out.println(h.getAbsolutePath()
[UPDATED] This is how you can achieve using plain Java and filter text from a variable passing as parameter:
Here is my directory: /tmp
And here is the code running:
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class GetAllFilesInDirectory {
public static void main(String[] args) throws IOException {
String filter = "BCM";
List<File> files = listFiles("/tmp", new CustomerFileFilter(filter));
for (File file : files) {
System.out.println("file: " + file.getCanonicalPath());
}
}
private static List<File> listFiles(String directoryName, CustomerFileFilter fileFilter) {
File directory = new File(directoryName);
List<File> files = new ArrayList<>();
// Get all files from a directory.
File[] fList = directory.listFiles(fileFilter);
if(fList != null) {
for (File file : fList) {
if (file.isFile()) {
files.add(file);
} else if (file.isDirectory()) {
files.addAll(listFiles(file.getAbsolutePath(), fileFilter));
}
}
}
return files;
}
}
class CustomerFileFilter implements FileFilter {
private final String filterStartingWith;
public CustomerFileFilter(String filterStartingWith) {
this.filterStartingWith = filterStartingWith;
}
#Override
public boolean accept(File file) {
return file.isDirectory() || file.isFile() && file.getName().startsWith(filterStartingWith);
}
}
This is the output:
file: /private/tmp/BCM01.txt
file: /private/tmp/BCM01
file: /private/tmp/subfolder1/BCM02.txt
Doing recursive calls to the method when finding a directory to also list the files form inside, and filtering by name the files before adding.
You want Files.walk:
try (Stream<Path> files = Files.walk(Paths.get("K:\\Jgencs"))) {
files.filter(f -> f.getFileName().toString().startsWith("BCM")).forEach(
file -> System.out.println(file));
}
I would like to search for files recursively. According to other solutions, I have already done a big portion of the code:
public static File[] getFiles(String path) {
File file = new File(path);
// Get the subdirectories.
String[] directories = file.list(new FilenameFilter() {
#Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
});
for (String dir : directories) {
// Doing recursion
}
// Get the files inside the directory.
FileFilter fileFilter = new FileFilter();
File[] files = file.listFiles(fileFilter);
return files;
}
FileFilter is just a custom filter of mine. My problem is that I don't know how to do the recursion in this case. Of course I could call getFiles() again for each subdirectory with the subdirectory path as argument but somehow the returning File array must be merged.
Does somebody have a solution?
Use the find() method.
/* Your filter can be initialized however you need... */
YourCustomFilter filter = new YourCustomFilter(extension, maxSize);
try (Stream<Path> s = Files.find(dir, Integer.MAX_VALUE, filter::test)) {
return s.map(Path::toFile).toArray(File[]::new);
}
This assumes your custom filter has a method called test() that accepts the file and its attributes; you'll need to rework your current file filter a bit to accommodate this.
boolean test(Path path, BasicFileAttributes attrs) {
...
}
Working example: http://screencast.com/t/buiyV9UiEa
You can try something like this:
//add this imports
import java.io.File;
import java.io.FilenameFilter;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
public static File[] getFiles(String path) {
File file = new File(path);
// Get the subdirectories.
String[] directories = file.list(new FilenameFilter() {
#Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
});
//Use a list to save the files returned from the recursive call
List<File> filesList = new ArrayList<File>();
if( directories != null){
for (String dir : directories) {
// Doing recursion
filesList.addAll( Arrays.asList(getFiles(path + File.separator + dir)) );
}
}
// Get the files inside the directory.
FileFilter fileFilter = new FileFilter();
File[] files = file.listFiles(fileFilter);
//Merge the rest of the files with the files
//in the current dir
if( files != null)
filesList.addAll( Arrays.asList(files) );
return filesList.toArray(new File[filesList.size()]);
}
Code tested and working. Hope this helps.
import java.util.Arrays;
import java.util.ArrayList;
Put a fail-safe right after you initialize file (in case of a bad path on the first call).
if (!file.isDirectory()) return new File[0];
And change the last part of your code to:
FileFilter fileFilter = new FileFilter();
ArrayList<File> files = new ArrayList(Arrays.asList(file.listFiles(fileFilter)));
for (String dir : directories) {
files.addAll(Arrays.asList(getFiles(dir)));
}
return files.toArray(new File[0]);
(the toArray method expands the array that you pass to it if it's too small) Ref
You should do something like this:
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
public static File[] getFiles(String path) {
File file = new File(path);
String[] directories = file.list(new FilenameFilter() {
#Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
});
ArrayList<File> files = Arrays.asList(file.listFiles(new FileFilter()));
for (String dir : directories) {
files.addAll(getFiles(dir));
}
return files.toArray(new File[list.size()]);
}
The new File[list.size()] is required because otherwise file.toArray() would return Object[].
Also, you should use a lambda expression instead of FilenameFilter, like so:
String[] directories = file.list((File current, String name) -> {
return new File(current, name).isDirectory();
});
What i wanna do is to recursively search for some files on the external sd-card. The problem is that the code is looking ok, but (assuming .txt files) it only shows me 7 files out of 100+ that are being spread throughout folders.
The code is this:
file = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
void makelist(File file){
if(file.isFile()){
if(SimpleAdapter.getFileType(file)==null)
mis.add(file);
else if(SimpleAdapter.getFileType(file).equalsIgnoreCase("text"))
doc.add(file);
}else if(file.isDirectory()){
for(File f:file.listFiles())
makelist(f);
}
}
Any idea how could i make it run correctly?
Assuming you are building two lists (misc files and doc files), try with below code which all all files other than text files to misc and text files to doc.
if(SimpleAdapter.getFileType(file) == null || !SimpleAdapter.getFileType(file).equalsIgnoreCase("text"))
mis.add(file);
else
doc.add(file);
Not sure why it is not working for you. Tried a test program and it worked perfectly...
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class FileChecker
{
/**
* #param args
*/
public static void main(String[] args) {
SimpleAdapterTest adapter = new SimpleAdapterTest();
adapter.makelist(new File("C:\\MYFolder"));
adapter.showList();
}
}
class SimpleAdapterTest
{
List<File> mis = new ArrayList<File>();
List<File> doc = new ArrayList<File>();
public static String getFileType(File f)
{
String Name = f.getName();
if (f.getName().endsWith(".txt") || Name.endsWith(".TXT")
|| Name.endsWith(".inf") || Name.endsWith(".INF"))
return "text";
return null;
}
public void makelist(File file){
if(file.isFile()){
if(SimpleAdapterTest.getFileType(file)==null)
mis.add(file);
else if(SimpleAdapterTest.getFileType(file).equalsIgnoreCase("text"))
doc.add(file);
}else if(file.isDirectory()){
for(File f:file.listFiles())
makelist(f);
}
}
public void showList()
{
for(File miscFile : mis)
{
System.out.println("Misc files = " + miscFile.getName());
}
for(File docfile : doc)
{
System.out.println("Doc files = " + docfile.getName());
}
}
}
HI I want to write a java program by which I can delete all the files of my computer having a specific extension or character pattern in name.I also want to apply wild card character on the name of file.
Thanks in advance
For your program to be really useful you need to do some more thinking, but for a starter;
import java.io.File;
import java.util.regex.Pattern;
private static void walkDir(final File dir, final Pattern pattern) {
final File[] files = dir.listFiles();
if (files != null) {
for (final File file : files) {
if (file.isDirectory()) {
walkDir(file, pattern);
} else if (pattern.matcher(file.getName()).matches()) {
System.out.println("file to delete: " + file.getAbsolutePath());
}
}
}
}
public static void main(String[] args) {
walkDir(new File("/home/user/something"), Pattern.compile(".*\\.mp3"));
}
Sidenote (not an answer, but you didn't ask something): Be aware of recursion.
public void deleteFilesWithExtension(final String directoryName, final String extension) {
final File dir = new File(directoryName);
final String[] allFiles = dir.list();
for (final String file : allFiles) {
if (file.endsWith(extension)) {
new File(aDirectoryName + "/" + file).delete();
}
}
}
Is it possible to use a regular expression to get filenames for files matching a given pattern in a directory without having to manually loop through all the files.
You could use File.listFiles(FileFilter):
public static File[] listFilesMatching(File root, String regex) {
if(!root.isDirectory()) {
throw new IllegalArgumentException(root+" is no directory.");
}
final Pattern p = Pattern.compile(regex); // careful: could also throw an exception!
return root.listFiles(new FileFilter(){
#Override
public boolean accept(File file) {
return p.matcher(file.getName()).matches();
}
});
}
EDIT
So, to match files that look like: TXT-20100505-XXXX.trx where XXXX can be any four successive digits, do something like this:
listFilesMatching(new File("/some/path"), "XT-20100505-\\d{4}\\.trx")
EDIT
Starting with Java8 the complete 'return'-part can be written with a lamda-statement:
return root.listFiles((File file) -> p.matcher(file.getName()).matches());
implement FileFilter (just requires that you override the method
public boolean accept(File f)
then, every time that you'll request the list of files, jvm will compare each file against your method. Regex cannot and shouldn't be used as java is a cross platform language and that would cause implications on different systems.
package regularexpression;
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegularFile {
public static void main(String[] args) {
new RegularFile();
}
public RegularFile() {
String fileName = null;
boolean bName = false;
int iCount = 0;
File dir = new File("C:/regularfolder");
File[] files = dir.listFiles();
System.out.println("List Of Files ::");
for (File f : files) {
fileName = f.getName();
System.out.println(fileName);
Pattern uName = Pattern.compile(".*l.zip.*");
Matcher mUname = uName.matcher(fileName);
bName = mUname.matches();
if (bName) {
iCount++;
}
}
System.out.println("File Count In Folder ::" + iCount);
}
}