I have a folder in a directory. I know, there is always only one file and it's a .txt file. But I don't know the filename.
How can I access it in Java? How must the path look like?
You could open the directory and go over its contents until you find the file:
public static File getTextFileInDirectory(String dirPath) {
File dir = new File(dirPath);
for (File f : dir.listFiles()) {
if (f.isFile() && f.getName().endsWith(".txt")) {
return f;
}
}
return null;
}
EDIT:
Based on the comments below, if it's safe to assume the directory always has a file in it, and there's nothing else in the directory (e.g., subdirectories), this code can be greatly simplified:
public static File getTextFileInDirectory(String dirPath) {
return new File(dirPath).listFiles()[0];
}
Since you know there will only be one file in the directory, you can get an array of the directory's files and return the first element if it exists, or null if it doesn't.
public static File getFileFromDir(File directory) {
File[] dirFiles = directory.listFiles();
return dirFiles.length > 0 ? dirFiles[0] : null;
}
Related
I have a folder called "all_users" in my java project under the src directory.How can I access the files(if there are any) in the all_users folder. I eventually want to loop through all the existing files in the "all_users" folder, comparing whether the file name is equal to a string i specify in the code.
Firstly, I tried File f = new File(System.getProperty("user.home")+File.pathSeparator + "all_users"); as the file object then later tried File dir = new File(TEST_PATH); Both returned false when i checked if it existed so i didn't set up the path correctly?
public class ValUtility {
static final String TEST_PATH = "./all_users/";
public static boolean validUsername(String user) {
File f = new File(System.getProperty("user.home") + File.pathSeparator + "all_users");
File dir = new File(TEST_PATH);
File[] directoryListing = f.listFiles();
System.out.println(f.exists());
System.out.println(directoryListing);
if (directoryListing != null) {
for (File child : directoryListing) {
// Do something with child
// think child is filename?
if (user.equals(child.getName())){
return false;
}
}
}
return true;
}
}
Please run...
System.out.println(System.getProperty("user.home"));
The above will inform you where you need to add a folder labeled 'all_users'. It is very unlikely that your 'user.home' property is set to your project's source file (src) folder.
I want to get the name of the folders from directory who only have .c and .h files.
below is my code but I am not getting that how exactly I can get the folder names who only have .c and .h files.
File directory = new File(directoryName);
//get all the files from a directory
if(directory.exists()){
File[] fList = directory.listFiles();
for (File file : fList){
if (file.isDirectory()){
System.out.println(file.getName());
System.out.println(file.getAbsolutePath());
}
Above code will take the input path for directory and prints the name of all sub folders or sub directories if the main directory is exist.and also prints the path.Now I only want the name of all sub folders from directory which have .c and .h files.
Thanks If anyone help me.
Try to take a look at Apache's DirectoryScanner
Using that we can mention the file extension types to be considered/omitted
DirectoryScanner scanner = new DirectoryScanner();
scanner.setIncludes(new String[]{"*.c", "*.h"});
https://ant.apache.org/manual/api/org/apache/tools/ant/DirectoryScanner.html
You can use a list and getParent() function like:
List<String> list;
File directory = new File(directoryName);
if(directory.exists()){
File[] fList = directory.listFiles();
for (File file : fList){
if (file.isDirectory()){
System.out.println(file.getName());
if(file.getName().contains(".c") || file.getName().contains(".h"))
list.add(file.getParent());
System.out.println(file.getAbsolutePath());
}
}
}
for(String item : list) {
System.out.println(item);
}
I've given a pure Java solution here, but if your directory structure is too deep or directories have thousands of files, this may not work out. In that case you may have to run an OS command and dump the output into Java. For instance if you use Unix (or Unix-based) system, you can use find to list directories and invoke the command from Java using ProcessBuilder.
Now the Java solution:
Create a custom FileNameFilter first. This will filter files based on extensions you pass.
public class ExtensionFilter implements FilenameFilter {
private String[] extensions;
public ExtensionFilter(String... extensions) {
this.extensions = extensions;
}
#Override
public boolean accept(File dir, String name) {
for (String extension : extensions) {
if ( name.toLowerCase().endsWith(extension.toLowerCase()) ) {
return true;
}
}
return false;
}
}
Create a FileFilter to help you filter for only directories (for recursion)
public class FolderFilter implements FileFilter {
#Override
public boolean accept(File path) {
return path.isDirectory();
}
}
Use recursion to build list of folder paths contains files with the given extension.
private static final FolderFilter folderFilter = new FolderFilter();
public List<String> recursiveSearch(File base, ExtensionFilter extFilter) {
List<String> paths = new ArrayList<>();
//Does current directory itself have files of given extension?
if (base.list(extFilter).length > 0) {
paths.add(base.getPath()); //Use base.getName() here instead, for just name
}
// Recurse through current directory's subfolders
for (File dir : base.listFiles(folderFilter)) {
paths.addAll(recurse(dir, extFilter));
}
return paths;
}
Finally, invoke it like so:
String basePath = "...";
File baseDir = new File(basePath);
ExtensionFilter extFilter = new ExtensionFilter(".c",".h");
List<String> folders = recurse(baseDir, extFilter);
This will now contain all paths (or names as mentioned above) of folders which have files with given extensions.
I'm creating a java program which takes parent path and deletes all the files and folders in the given path. I'm able to delete files and folder's files inside another folder in the parent folder but not able to delete folders at 3rd level.
Here's my code:
package com.sid.trial;
import java.util.List;
import java.io.File;
import java.util.ArrayList;
public class DeleteFilesOfDirectoryWithFilters {
public static void main(String[] args) {
String parentPath = "D:\\tester";
List<String> folderPaths = deleteFiles(parentPath);
deleteFolders(folderPaths);
}
public static void deleteFolders(List<String> folderPaths) {
for(String path : folderPaths){
File folder = new File(path);
if(folder.delete())
System.out.println("Folder "+folder.getName()+" Successfully Deleted.");
}
}
public static List<String> deleteFiles(String path){
File folder = new File(path);
File[] files = folder.listFiles();
List<String> folderPaths = new ArrayList<String>();
String folderPath = path;
if(files.length == 0){
System.out.println("Directory is Empty or No FIles Available to Delete.");
}
for (File file : files) {
if (file.isFile() && file.exists()) {
file.delete();
System.out.println("File "+file.getName()+" Successfully Deleted.");
} else {
if(file.isDirectory()){
folderPath = file.getAbsolutePath();
char lastCharacter = path.charAt(path.length()-1);
if(!(lastCharacter == '/' || lastCharacter == '\\')){
folderPath = folderPath.concat("\\");
}
/*folderPath = folderPath.concat(file.getName());*/
System.out.println(folderPath);
folderPaths.add(folderPath);
}
}
}
for(String directoryPath : folderPaths){
List<String> processedFiles = new ArrayList<String>();
processedFiles = deleteFiles(directoryPath);
folderPaths.addAll(processedFiles);
}
return folderPaths;
}
}
You can use the ""new"" Java File API with Stream API:
Path dirPath = Paths.get( "./yourDirectory" );
Files.walk( dirPath )
.map( Path::toFile )
.sorted( Comparator.comparing( File::isDirectory ) )
.forEach( File::delete );
Note that the call to sorted() method is here to delete all files before directories.
About one statement, and without any third party library ;)
You should consider using Apache Commons-IO. It has a FileUtils class with a method deleteDirectory that will recursively delete.
Note: Apache Commons-IO (as for version 2.5) provides utilities only for legacy java.io API (File and friends), not for Java 7+ java.nio API (Path and friends).
You can recursively traverse through the folder and delete each file one by one. After deleting all the files in one folder, delete the folder. Something similar to following code should work:
public void delete(File path){
File[] l = path.listFiles();
for (File f : l){
if (f.isDirectory())
delete(f);
else
f.delete();
}
path.delete();
}
You can do the following, your recursion is longer than needed.
public static void deleteFiles (File file){
if(file.isDirectory()){
File[] files = file.listFiles(); //All files and sub folders
for(int x=0; files != null && x<files.length; x++)
deleteFiles(files[x]);
}
else
file.delete();
}
Explanation:
When invoke deleteFiles() on a file, the else statement gets triggered, the single file will be deleted with no recursion.
When invoke deleteFiles() on a folder, the if-statement gets triggered.
Get all the entries (files of folders residing in the folder) as an array
If there exist sub-entries, for each entry, recursively delete the sub-entry (the same process (1 and 2) repeats).
Be careful when implementing deletion of file and folders. You may want to print out all the files and folders name first instead of deleting them. Once confirmed it is working correctly, then use file.delete().
I am not asking how to check if a file exists or how to check if a file is in a specific directory level. Rather I want to know how to check if an existing file is anywhere underneath a specified directory.
Obviously if a file is a direct child of a directory that is easy to check. But what I want to be able to do is efficiently check if an existing file is in a directory including any possible subdirectory. I'm using this in an Android project where I am keeping fine grain control over my cache and I want a utility method to check if a file I may be manipulating is in my cache folder.
Example:
cache dir
/ \
dir file1
/ \
file2 file3
isCacheFile(file2) should return true
Currently I have a method that does it like so
private static final File cacheDir = AssetManager.getInstance().getCacheDir(); // Not android.content.res.AssetManager
private static final String cacheDirName = cacheDir.getAbsolutePath();
public static boolean isCacheFile(File f) {
if (!f.exists()) return false;
return f.getAbsolutePath().startsWith(cacheDirName);
}
However, I am inclined to believe there is a better way to do this. Does anyone have any suggestions?
If you have a known path (in the form of File f), and you want to know if it is inside a particular folder (in the form of File cacheDir), you could simply traverse the chain of parent folders of your file and see if you meet the one you are looking for.
Like this:
public static boolean isCacheFile(File f) {
while (f.getParentDir()!=null) {
f = f.getParentDir();
if (f.equals(cacheDir)) {
return true;
}
}
return false;
}
boolean isContains(File directory){
File[] contents = directory.listFiles();
if (contents != null) {
for(int i = 0; i < contents.length; i++){
if(contents[i].isDirectory())
isContains(contents[i]);
else if(contents[i].getName().equals(*your_file_name*))
return true;
}
}
return false;
}
You could do it by recursion, by calling if the file exists in each sub-directory.
first check if the file exists in the root directory.
boolean exist = new File(rootDirectory, temp).exists();
then if the file wasn't in the root directory, then list all the files and call the method again in the sub-directoy files recursionally until you find the file or there are no more sub-directories.
public String getPathFromFileName(String dirToStart,Sring fileName){
File f = new File(dirToStart);
File[] list = f.listFiles();
String s="null";
for(int i=0;i<list.length;i++){
if(list[i].isFile()){
//is a file
if(fileName.equals(list[i])){
s=dirToStart+"/"+fileName;
break;
}
}else{
//is a directory search further.
getPathFromFileName(dirToStart+list[i]);
}
}
return s;
}
call this method by passing the parent directory name and the file name to search in subdirectories.
you check the return value if it is not equal to "null", then the files path is returned.
Ok so part of my program searches the C drive for all mp3 files, the only problem is that it won't go into and subfolders. Here is my code so far.
public static List<String> ListFiles() {
List<String> files = new ArrayList<String>();
File folder = new File("C:/");
File[] listOfFiles = folder.listFiles();
for (File file : listOfFiles) {
if (file.isFile() && file.toString().contains(".mp3")) {
String fileS = file.getName();
files.add(fileS);
}
}
return files;
}
Try a recursive approach. The path is the current directory that you're in. Recursively call this on each folder and you will get to each file.
public void walk(String path) {
File root = new File(path);
File[] list = root.listFiles();
if (list == null) return;
for (File f : list) {
if (f.isDirectory()) {
walk(f.getAbsolutePath());
}
else {
//do what you want with files
}
}
}
Test whether file is a folder. If it is, pass it to ListFiles and append the return value to files.
For this to work, you need to change ListFiles to accept a File object as argument and start your search with this File instead of with "C:/"
Look into DirectoryStream<Path> class and the Files.isDirectory() method. Basically what you want to do is to check whether each Path is a file or directory.
If it is a directory, you call your method again. Else, you continue iterating.
Globbing is also possible with a directory stream. Saves you a lot of time instead of having to manually check file extensions.
If you wish to continue with your method or with directory stream, you will need to make a few modifications to your program to accomodate recursion.
If you want to do this yourself, you need to make it recursive. Which is what Oswald is getting at. A recursive method is a method that calls itself. So when you search a folder, for each element in it, if its an mp3, add it to the list, if its a folder, call your method again passing that folder in as the input.
I know it's Java question but why not just use Groovy and do it like:
static List<String> listMp3s() {
List<String> files = []
File rootFolder = new File('C:/')
rootFolder.eachFileRecurse(FileType.FILES) {
if (it.name.endsWith('.mp3')) {
files << it.name
}
}
return files
}