As part of my app i need to have file browser that lists only specific folders.
For eg list only those folders in the path that an image file in any of its subfolders in any level.
I could do it using recursion. But it affects performance. Especially finding folders at top level need many recursive calls. Is there a better way to do it
Please see my code below
public List<GeneralFileItem> getGridItemsList(String root) {
List<GeneralFileItem> gridItemsList = new ArrayList<GeneralFileItem>();
File file;
file = new File(root);
File list[] = file.listFiles();
if (list.length == 0) {
return null;
}
for (int i = 0; i < list.length; i++) {
GeneralFileItem item = new GeneralFileItem();
File temp_file = new File(file.getAbsolutePath(), list[i].getName());
if (hasPhoto(temp_file)) {
item.setPath(file.getAbsolutePath() + "/" + list[i].getName());
item.setName(list[i].getName());
if (temp_file.listFiles() != null) {
item.setType(GeneralFileItem.DIRECTORY_TYPE);
} else {
item.setType(GeneralFileItem.FILE_TYPE);
}
gridItemsList.add(item);
//Log.i(TAG,"added"+list[i].getName());
}
}
return gridItemsList;
}
private boolean hasPhoto(File temp_file) {
//Log.i(TAG,temp_file.getName());
if (temp_file.listFiles() == null) {
if (temp_file.getName().toUpperCase().endsWith(("JPG"))) {
//Log.i(TAG,temp_file.getName()+ "is a photo");
return true;
} else
return false;
}
else{
File list[] = temp_file.listFiles();
for (int i = 0; i < list.length; i++) {
if(hasPhoto(list[i]))
return true;
}
}
return false;
}
I want to know if there is any other way than recursive search. How are the files maintained in Android. I know that various file systems are supported and it varies from hardware manufaturer . I would like to know if there is a way like if there is FileTable from which i can get all .jpg files .
use FilenameFilter to search for specirfic type of files.
presently you are checking only current directory.However if you wish to search recursively then you will have to check if each file found is a directory or not
Your algo would be something like
File file;
file = new File(root);
File list[] = file.listFiles();
if (list.length == 0) {
return null;
}
for (int i = 0; i < list.length; i++) {
if(list[i].isDirectory()){
//Then go inside it to search for specific file
File subList[] = list[i].listFiles();
//search for jpg..
}else if("is this jpg"){
//Add to list
}
}
To simplify this you could segregate these into methods as per your requirement.
Here's something I came up! It works like a charm!
First you must create a File, this one is root of SD card
File = rootPrimary = new File(Environment.getExternalStorageDirectory());
than you must list all the files in to a File []
File[] fileArray = rootDirectory.listFiles();
Then you create a ArrayList and set it equal to a method i've created and pass the File[] in.
ArrayList<File> alFolders = new ArrayList<File>();
alFolder = putImgFldr(fileArray);
This method will add all dorectoryes that contain images with .jpg and .png extension.
private ArrayList<File> putImgFldr(File[] fileArray) {
// TODO Auto-generated method stub
ArrayList<File> a = new ArrayList<File>();
for (int i = 0; i < fileArray.length; i++) {
if (fileArray[i].isDirectory()) {
//if file is folder pass that file trough this method
a.addAll(putImgFldr(fileArray[i].listFiles()));
} else if (fileArray[i].getAbsolutePath().endsWith(".jpg") || fileArray[i].getAbsolutePath().endsWith(".png")) {
// if file is img ad it's parent, folder to ArrayList
a.add(fileArray[i].getParentFile());
// this finishes the file searching
// because the image has allready bean found
i = fileArray.length + 1;
}
}
return a;
}
now You can add another File [] to alFolders if nessesery
alFolders.addAll(putImgFldr(secFileArray));
One more example of listing files and directories using Java 8 filter. For instance, here I am using just jpeg images
public static void main(String[] args) {
System.out.println("Files!!");
try {
Files.walk(Paths.get("."))
.filter(Files::isRegularFile)
.filter(c ->
c.getFileName().toString().substring(c.getFileName().toString().length()-4).contains(".jpg")
||
c.getFileName().toString().substring(c.getFileName().toString().length()-5).contains(".jpeg")
)
.forEach(System.out::println);
} catch (IOException e) {
System.out.println("No jpeg or jpg files");
}
System.out.println("\nDirectories!!\n");
try {
Files.walk(Paths.get("."))
.filter(Files::isDirectory)
.forEach(System.out::println);
} catch (IOException e) {
System.out.println("No Jpeg files");
}
}
Related
Is it possible to develop a Java application that can read all files and directories in the device's memory?
I think it's not possible (for security reasons), but I need another opinion.
You can do it like this.
I will take path is the device storage.
If you are using Android Studio or a likewise tool, put the debug point next to:
File[] dir = new File(path).listFiles();
And you will see the file/folder hierarchy.
path = Environment.getExternalStorageDirectory().toString()
public static ArrayList<String> listFoldersAndFilesFromSDCard(String path) {
ArrayList<String> arrayListFolders = new ArrayList<String>();
try {
File[] dir = new File(path).listFiles();
// Here 'dir' will give you a list of folder/files in the hierarchy
if (null != dir && dir.length > 0) {
for (int i = 0; i < dir.length; i++) {
if (dir[i].isDirectory()) {
arrayListFolders.add(new File(dir[i].toString()).getName());
// Here you can call recursively this
// function for file/folder hierarchy
}
else {
// Do whatever you want with the files
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return arrayListFolders;
}
I am trying to find all directories on an Android device that contain images (internal as well as external storage).
Basically, I try to get all the directories that are listed in the native gallery application
So for example:
All images
Downloads
My Favourites
Whatsapp Pictures
...
How does one accomplish this? I think it is related to MediaStorage.Images.Media and so on, but the documentation is not very helpful there and a lot of google searches didn't help as well.
Thanks to #BlazingFire, who did not fully answer my question, but provided some code I could work with and have now my desired result:
public ArrayList<String> getFile(File dir) {
File listFile[] = dir.listFiles();
if (listFile != null && listFile.length > 0) {
for (File file : listFile) {
if (file.isDirectory()) {
getFile(file);
}
else {
if (file.getName().endsWith(".png")
|| file.getName().endsWith(".jpg")
|| file.getName().endsWith(".jpeg")
|| file.getName().endsWith(".gif")
|| file.getName().endsWith(".bmp")
|| file.getName().endsWith(".webp"))
{
String temp = file.getPath().substring(0, file.getPath().lastIndexOf('/'));
if (!fileList.contains(temp))
fileList.add(temp);
}
}
}
}
return fileList;
}
It only adds parent directories of images and only if they have not yet been added. I also included .bmp and .webp as valid image file extensions
You can use this code to find picture folders in Storage -
private ArrayList<File> fileList = new ArrayList<File>();
...
public ArrayList<File> getfile(File dir) {
File listFile[] = dir.listFiles();
if (listFile != null && listFile.length > 0) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].getName().endsWith(".png")
|| listFile[i].getName().endsWith(".jpg")
|| listFile[i].getName().endsWith(".jpeg")
|| listFile[i].getName().endsWith(".gif"))
{
String temp = file.getPath().substring(0, file.getPath().lastIndexOf('/'));
fileList.add(temp);
}
}
}
return fileList;
}
And then you can call the ArrayList this way -
File root = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
getFile(root);
for (int i = 0; i < fileList.size(); i++) {
String stringFile = fileList.get(i).getName();
Do whatever you want to do with each filename here...
}
I am building an Android app that writes files in the format of my custom .fire extension.
I need to access them all at once and put them in a ListView. Could someone please help me to fetch them via an activity or Async Task Manager?
You can write an Async Task to fetch the .fire files from the folder into which you are writing them initially and dynamically add the filenames into the listview.
You can do something like this in your async task:
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
File root = android.os.Environment.getExternalStorageDirectory();
File dir = new File(root.getAbsolutePath() + "/"+FolderWhichContainsyourFiles);
File[] listOfFiles = dir.listFiles();
for (int count = 0; count < listOfFiles.length; count++) {
File file = listOfFiles[count];
if (file.isFile() && file.getName().endsWith(".fire")) {
String fileName = file.getName();
//Here you can dynamically add this name into the ListView
}
}
}
You need to use an ArrayAdapter and add elements to the ArrayAdapter dynamically. It is brilliantly explained here: Dynamically add elements to a listView Android
if you want to find files recursively:
private static List<File> filesList = new ArrayList<File>();
public static List<File> recursiveList(String filePath) {
try {
File[] dir = new File(filePath).listFiles();
for (File item : dir) {
if (item.isDirectory()) recursiveList(item.getAbsolutePath());
else if (item.isFile() && item.getName().endsWith(".fire"))
filesList.add(item);
}
return filesList;
} catch (Exception e) {
return null;
}
}
and to retrieve files in activity:
List<File> files = recursiveList("/sdcard/Music/");
for (File file : files)
adapterFilesList.add("" + file.getName());
I am creating a directory in internal memory of device for storing files for application use.I am using:
File dir = context.getDir(userfavorites, Context.MODE_PRIVATE);
The above code will create a new directory if it does not exists or returns me the existing file object if directory has already been created.What I want to check is the number and name of files this directory contains.How do I use this file object to accomplish this task.
NOTE:I don't want to use external memory of device.And I can't avoid creating directory as well because the files in directory has to be separated from other files that are not in directory.
UPDATED CODE:
private static boolean IsFoldercontainsFiles(Context context) {
// TODO Auto-generated method stub
File dir = context.getDir(USER_FAV, Context.MODE_PRIVATE);
if (dir.exists()) {
if (dir.listFiles() == null){
return false;} //it never execute this line even though its null
else{
File childfile[] = dir.listFiles();
Log.i("file no is ", Integer.toString(childfile.length));
if (childfile.length == 0) {
return false;
} else {
return true;
}
}
} else {
return false;
}
}
Thanks in advance
Check the listFiles method of File that will give you the list of children.
File file=new File("/mnt/sdcard/yourfolder");
File[] list = file.listFiles();
int count = 0;
for (File f: list){
String name = f.getName();
if (name.endsWith(".jpg") || name.endsWith(".mp3") || name.endsWith(".some media extention"))
count++;
System.out.println("170 " + count);
}
try this
File childfile[] = dir .listFiles();
for (File file2 : childfile) {
Log.v("file name is ", file2.getName());
}
here listFiles() return all the childfiles for the "dir" and iterating this will help you to get the names of the childfiles
Simple:
File dir = new File(path); // "/mnt/sdcard/yourfolder"
long totalNumFiles = dir.listFiles().length;
Try this sample of code for getting number of files in a directory
private int getNumberOfFiles() throws FileNotFoundException {
File outFile = new File(outFolder);
if (!outFile.exists())throw new FileNotFoundException();
int numberofFiles = outFile.listFiles(new FileFilter() {
#Override
public boolean accept(File file) {
return (file.getPath().startsWith("frame_")&&(file.getPath().endsWith(".jpg")||file.getPath().endsWith(".jpeg")));
}
}).length;
return numberofFiles;
}
The listFiles method of the File class returns an array of File objects, one for each file or directory in the directory.
One can use recursion to find all files within a directory and its subdirectories.
fun File.getFileCountRecursively(): Int {
var fileCount = 0
if (exists() && isDirectory) {
listFiles()?.forEach { child ->
fileCount += if (child.isDirectory) child.getFileCountRecursively() else 1
}
}
return fileCount
}
I want to search for a particular file in my sd card . So i am trying to list complete files and search for the pattern. Please see code below
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String root_sd = Environment.getExternalStorageDirectory().toString();
file = new File(root_sd);
listfiles( new File(root_sd));
}
public void listfiles(File file) {
//file = new File(path);
// file = new File( root_sd ) ;
File list[] = file.listFiles();
Log.i("DIR", "PATH" +file.getPath());
for (int i = 0; i < list.length; i++) {
// myList.add( list[i].getName() );
File temp_file = new File(file.getAbsolutePath(),list[i].getName());
Log.i("DIR", "PATH" +temp_file.getAbsolutePath());
if (temp_file.isFile() && temp_file.listFiles() != null) {
Log.i("inside", "call fn");
listfiles(temp_file);
} else {
if (list[i].getName().toLowerCase().contains("pattern1"))
Log.i("File", i + list[i].getName());
if (list[i].getName().toLowerCase().contains("pattern2"))
Log.i("File", i + list[i].getName());
}
}
Here only first level of search is happening . This condition if (temp_file.isFile() && temp_file.listFiles() != null)
is always returning false and thus recursive call not happening.
Please help me to fix it. Thanks for your answer and time.
if the temp_file.isFile() returns true then it means it is a file and hence temp_file.listFiles() automatically becomes null thus making your entire statement false. Thus your combined statement returns a false always. What you need is a || in place of &&.