I create some folders into assets. Each folder contains files that I would like to list. I am using following code but I always get a null value for fileList. Thank you.
I used, listFiles("/assets/images/","nothing");
private void listFiles(String dirFrom, String dirTo) {
File f = new File(dirFrom);
String fileList[] = f.list();
if (fileList != null)
{
for ( int i = 0;i<fileList.length;i++)
{
Log.d("",fileList[i]);
}
}
}
You'll probably want to do this:
private void listFiles(String dirFrom) {
Resources res = getResources(); //if you are in an activity
AssetManager am = res.getAssets();
String fileList[] = am.list(dirFrom);
if (fileList != null)
{
for ( int i = 0;i<fileList.length;i++)
{
Log.d("",fileList[i]);
}
}
}
Also your function call should be: listFiles("images"); if you want to list images.
Simplest would surely be this:
String[] fileList = getAssets().list("images");
Related
I am doing a memory game and in one of my method, I'm trying to create all cards by using File, but it could not run. It always goes to "Picture path is empty", but I want it to run.
/*
Create all Cards.
*/
public static List<Card> createAllCards(String dirPath){
//System.out.println("create all cards");
List<Card> cardList = new ArrayList<>();
File file = new File(dirPath);
File[] pictures = file.listFiles();
//System.out.println("file:" + Arrays.toString(pictures));
int index;
String type = "";
String cardPath;
if (pictures != null){
for (File picture : pictures) {
index = picture.getName().lastIndexOf(".");
if (picture.isFile()){
if (index > 0) {
type = picture.getName().substring(index + 1);
System.out.println("output:" + type);
if (type.equals("png")){
cardPath = picture.getPath();
//cardPath = cardPath.replaceAll("\\\\","\\\\\\\\");
cardList.add(new Card(picture.getName(),cardPath));
}
}
}
}
}else {
System.out.println("Picture path is empty");
}
return cardList;
}
}
The java.io.File class is obsolete. The java.nio.file package is its replacement.
The File class was part of Java 1.0 and did a poor job of reporting errors. Many of its methods return null or false, which tells you nothing about what actually went wrong. The classes in java.nio.file will actually throw exceptions telling you exactly what went wrong.
Specifically, you want to use the Path and Files classes:
try (DirectoryStream<Path> pictures =
Files.newDirectoryStream(Paths.get(dirPath), "*.png")) {
for (Path picture : pictures) {
if (Files.isRegularFile(picture)) {
cardList.add(
new Card(picture.getFileName().toString(), cardPath));
}
}
} catch (IOException e) {
e.printStackTrace();
}
This probably won’t make your program work, but it will give you the information you need to resolve the problem.
Okay, I used your code and modified this, as per your requirement.
Have a look:
NOTE: My photos folder is in the room directory
import java.io.File;
import java.util.ArrayList;
import java.util.List;
class Card{
String photoName,cardPath;
public Card(String name, String cardPath2) {
this.photoName = name;
this.cardPath = cardPath2;
}
}
public class readPhotos {
public static List<Card> createAllCards(String dirPath){
//System.out.println("create all cards");
List<Card> cardList = new ArrayList<>();
File file = new File(dirPath);
File[] pictures = file.listFiles();
//System.out.println("file:" + Arrays.toString(pictures));
int index;
String type = "";
String cardPath;
if (pictures != null){
for (File picture : pictures) {
index = picture.getName().lastIndexOf(".");
if (picture.isFile()){
if (index > 0) {
type = picture.getName().substring(index + 1);
System.out.println("output:" + type);
if (type.equals("png")){
cardPath = picture.getPath();
//cardPath = cardPath.replaceAll("\\\\","\\\\\\\\");
cardList.add(new Card(picture.getName(),cardPath));
}
}
}
}
}else {
System.out.println("Picture path is empty");
}
return cardList;
}
public static void main(String...args)
{
List<Card> cardList = readPhotos.createAllCards("./photos/");
System.out.println(cardList);
}
}
add your photos path accordingly... when calling the method readPhotos.createAllCards("./photos/");
I want to find all the txt files in directory and in the nested sub-directories. If found, I want to move that from one location to another.
The below code works fine, if i don't have any nested sub-directories.
The problem with the below code is, Once it find the nested directories it return the file only from that particular nested sub-directory.
But I want all the txt files in my directory ( parent and its nested sub-directories ).
public class FilesFindingInDirectory {
static ArrayList<File> al = new ArrayList<File>();
static File fileLocation = null;
public static void main(String[] args) throws IOException {
File filePath = new File("C:\\Users\\Downloads");
File[] listingAllFiles = filePath.listFiles();
ArrayList<File> allFiles = iterateOverFiles(listingAllFiles);
for (File file : allFiles) {
if(file != null) {
String fileName = file.getName();
String sourceFilepath = file.getAbsolutePath();
File targetFilePath = new File("D:\\TestFiles");
String targetPath = targetFilePath.getPath();
Files.move(Paths.get(sourceFilepath), Paths.get("D:\\TestFiles\\" + fileName));
}
}
}
public static ArrayList<File> iterateOverFiles(File[] files) {
for (File file : files) {
if (file.isDirectory()) {
iterateOverFiles(file.listFiles());// Calls same method again.
} else {
fileLocation = findFileswithTxtExtension(file);
if(fileLocation != null) {
System.out.println(fileLocation);
al.add(fileLocation);
}
}
}
return al;
}
public static File findFileswithTxtExtension(File file) {
if(file.getName().toLowerCase().endsWith("txt")) {
return file;
}
return null;
}
}
You're already using the nio Files API to move the files, why not using it to iterate over the files?
List<Path> txtFiles = Files.walk(Paths.get("C:\\Users\\Downloads"))
//use to string here, otherwise checking for path segments
.filter(p -> p.toString().endsWith(".txt"))
.collect(Collectors.toList());
If you don't need that intermediary list, you could as well run your move operation in a foreach terminal operation
Files.walk(Paths.get("C:\\Users\\Downloads"))
.filter(p -> p.toString().endsWith(".txt"))
.forEach(p -> {
try {
Files.move(p, Paths.get("D:\\TestFiles", p.getFileName().toString()));
} catch (IOException e) {
e.printStackTrace();
}
});
From your recursive function remove this line:
return al;
change this line to just call the recursive function:
ArrayList<File> allFiles = iterateOverFiles(listingAllFiles);
to
iterateOverFiles(listingAllFiles);
and finally change your for loop to iterate over the static field al.
for (File file : allFiles) {
to
for (File file : al) {
Explanation: There are numerous ways to write recursion for this problem. In this case you have a global variable for collecting the results. Each iteration should add to that global result, and simply return. At the end of all recursion calls, the global variable will contain all the results.
You are properly calling the function recursively, but you're then ignoring its return value. Instead, you should append it to the result list:
public static List<File> iterateOverFiles(File[] files) {
List<File> result = new ArrayList<>();
for (File file : files) {
if (file.isDirectory()) {
result.addAll(iterateOverFiles(file.listFiles()); // Here!
} else {
fileLocation = findFileswithTxtExtension(file);
if(fileLocation != null) {
result.add(fileLocation);
}
}
}
return result;
}
Just iterate over a directory, skipping any non-directory entries and entries that do not have the desired extension. Add all files with the correct extension to a result, and do that recursively for each directory.
public class FilesFindingInDirectory {
public static void main(String[] args) throws IOException {
File filePath = new File("C:\\Users\\Downloads");
Collection<File> allFiles = findFiles(filePath, ".txt");
allFiles.forEach(file -> {
String fileName = file.getName();
String sourceFilepath = file.getAbsolutePath();
File targetFilePath = new File("D:\\TestFiles");
String targetPath = targetFilePath.getPath();
Files.move(Paths.get(sourceFilepath), Paths.get("D:\\TestFiles\\" + fileName));
}
}
}
public static List<File> findFiles(File dir, String extension) {
File[] files = dir.listFiles(f -> f.isDirectory() || f.getName().toLowerCase().endsWith(extension);
ArrayList<File> result = new ArrayList<>();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
result.addAll(findFiles(file, extension);
} else {
result.add(file);
}
}
return result;
}
}
I am not able get root path usb otg in Android Nougat working fine till marshmallow. even able to get root path of sd card .can any body help me out from this i am frustrated from couple days.
Here is my code that return root path upto marshmallow and nougat sdcard. but not usb otg
public static String FileSystem() {
String path = null;
String SD_CARD_DIR = null;
try {
Process mount = Runtime.getRuntime().exec("mount");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(mount.getInputStream()));
mount.waitFor();
// String extPath = Environment.getExternalStorageDirectory().getPath();
// String isMedai = Environment.getExternalStorageState();
// if(Environment.MEDIA_MOUNTED.equalsIgnoreCase(isMedai)){
// String root = Environment.getRootDirectory().getPath();
// path = Environment.getExternalStoragePublicDirectory(DIRECTORY_EDUCOMP).getPath();
// }
String line;
String strFileSystem = null;
while ((line = bufferedReader.readLine()) != null) {
String[] split = line.split("\\s+");
for (int i = 0; i < split.length - 1; i++) {
if (SD_CARD_DIR == null) {
File mainroot = new File(split[i]);
File f[] = mainroot.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory();
}
}); // Get First level folders /mnt
if (f != null) {
for (File aFile : f) {
File[] filenames = aFile.listFiles(); // Get second level
// folders
// /mnt/sdcard so on
// and math Educomp
// folder
if (filenames != null) {
for (File ff : filenames) {
String eduFileName = ff.getName();
if (eduFileName.equals("Temp")) {
File[] listEducompfile = ff.listFiles();
if (listEducompfile != null) {
for (File fff : listEducompfile) {
String contentFileName = fff.getName();
if (contentFileName.equals("ts")) {
SD_CARD_DIR = aFile
.getAbsolutePath() + "/";
break;
}
}
}
} else {
File[] filenamesList = ff.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory();
}
});
if (filenamesList != null) {
for (File fff : filenamesList) {
String eduFileNamess = fff.getName();
if (eduFileNamess.equals("Temp")) {
File[] listEducompfile = fff.listFiles();
if (listEducompfile != null) {
for (File fffds : listEducompfile) {
String contentFileName = fffds.getName();
if (contentFileName.equals("ts")) {
return SD_CARD_DIR = ff + "/";
}
}
}
}
}
}
}
}
}
}
}
}
// SD_CARD_DIR = DEFAULT_SD_CARD_DIR;
}
return SD_CARD_DIR;
}
return path;
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
File dir = new File ("/");
File files = dir.listFiles();
You will not get a listing in Nougat for the root directory. You could have told us that.
`files==null` or files.length()==0
Nougat does not allow listing root. There are several other directories too that you cannot list anymore under Nougat.
You can check this approach on Nougat. But there is no way to make difference between removable SD card and USB flash if they are both connected to your device simultaneously.
Your approach - parsing mount file - does not work for some (chineese?) devices because string entry for internal memory may be completely the same as for removable SD card.
P.S. It is a user responsibility to find out where is USB flash or removable SD card in a "well" designed app. You should not do that by himself because Android does not provide public API for this purpose except Intent.ACTION_OPEN_DOCUMENT_TREE to call a built-in file chooser to interact with user in order to choose folder.
P.P.S INTERACTION WITH USER:
Create button with name "Show USB OTG Root" and onClick method containing
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);//http://stackoverflow.com/questions/28605278/android-5-sd-card-label
startActivityForResult(intent, REQUEST_CODE_USB_ACCESS);
In onActivityResult callback you have to catch user answer when he choose USB OTG root in internal Android chooser:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_USB_ACCESS:
if (data.getData() != null) {
int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(data.getData(), takeFlags);
DocumentFile documentFile = DocumentFile.fromTreeUri(this, data.getData());
}
}
}
documentFile is an access object representing USB OTG root (if user did not make mistake when choosing). You can make some file operation like documentFile.listFiles() on it. There is no other way to operate with files on removable media in public API starting from Lollipop. I.e. your desired path to USB OTG can not be obtained as a string from some public API method.
i am trying to get the correct path to the sd card that is inside my samsung s4 android device through my app but when i try the above paths:
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
String pathTwo = Environment.getExternalStorageDirectory().getAbsolutePath();
String path3 = getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
It gets the private none-writable path of /storage/emulated/0 instead of the correct path of storage/sdcard1
I found the correct path via File explorer using the Android Device monitor but i do not want to hard code the path as the path can be different depending on the device.
kind regards
For all devices
String sSDpath = null;
File fileCur = null;
for( String sPathCur : Arrays.asList( "MicroSD","external_SD","sdcard1","ext_card", "external_sd", "ext_sd", "external", "extSdCard", "externalSdCard")) // external sdcard
{
fileCur = new File( "/mnt/", sPathCur);
if( fileCur.isDirectory() && fileCur.canWrite())
{
sSDpath = fileCur.getAbsolutePath();
break;
}
if( sSDpath == null) {
fileCur = new File( "/storage/", sPathCur);
if( fileCur.isDirectory() && fileCur.canWrite())
{
sSDpath = fileCur.getAbsolutePath();
break;
}
}
if( sSDpath == null) {
fileCur = new File( "/storage/emulated", sPathCur);
if( fileCur.isDirectory() && fileCur.canWrite())
{
sSDpath = fileCur.getAbsolutePath();
Log.e("path",sSpath);
break;
}
}
}
100% working, tested on multiple device.
Based on a previous answer, the path to external SD card actually varies with different device manufactures.
"Environment.getExternalStorageDirectory() refers to whatever the device manufacturer considered to be "external storage". On some devices, this is removable media, like an SD card. On some devices, this is a portion of on-device flash. Here, "external storage" means "the stuff accessible via USB Mass Storage mode when mounted on a host machine", at least for Android 1.x and 2.x.
But the question is about external SD. How to get a path like "/mnt/sdcard/external_sd" (it may differ from device to device)?
Android has no concept of "external SD", aside from external storage, as described above.
If a device manufacturer has elected to have external storage be on-board flash and also has an SD card, you will need to contact that manufacturer to determine whether or not you can use the SD card (not guaranteed) and what the rules are for using it, such as what path to use for it."
Based on this answer.
So, There is no absolute way to get this path via code.
As gilonm mentioned, external (removable) Sd path varies from device to device, but I wrote a method, which iterates through all the different ext paths that the different manufacturers use, and then it finds the exact match.
It returns empty String if path isn't found. If a path is found, you still need to verify whether the card is inserted or not. (By checking if sub-folders exist on that path)
Note: I used StreamSupport library inside the method, so you'll need to download the jar file and add it to libs folder of your project and that's it, it'll work!
public static String getExternalSdPath(Context context) {
List<String> listOfFoldersToSearch = Arrays.asList("/storage/", "/mnt/", "/removable/", "/data/");
final List<String> listOf2DepthFolders = Arrays.asList("sdcard0", "media_rw", "removable");
final List<String> listOfExtFolders = Arrays.asList("sdcard1", "extsdcard", "external_sd", "microsd", "emmc", "ext_sd", "sdext",
"sdext1", "sdext2", "sdext3", "sdext4");
final String[] thePath = {""};
Optional<File> optional = StreamSupport.stream(listOfFoldersToSearch)
.filter(new Predicate<String>() {
#Override
public boolean test(final String s) {
File folder = new File(s);
return folder.exists() && folder.isDirectory();
}
}) //I got the ones that exist and are directories
.flatMap(new Function<String, Stream<File>>() {
#Override
public Stream<File> apply(final String s) {
try {
List<File> files = Arrays.asList(new File(s).listFiles());
return StreamSupport.stream(files);
} catch (NullPointerException e) {
return StreamSupport.stream(new ArrayList<File>());
}
}
}) //I got all sub-dirs of the main folders
.flatMap(new Function<File, Stream<File>>() {
#Override
public Stream<File> apply(final File file1) {
if (listOf2DepthFolders.contains(file1.getName()
.toLowerCase())) {
try {
List<File> files = Arrays.asList(file1.listFiles());
return StreamSupport.stream(files);
} catch (NullPointerException e) {
return StreamSupport.stream(Collections.singletonList(file1));
}
} else
return StreamSupport.stream(Collections.singletonList(file1));
}
}) //Here I got all the 2 depth and 3 depth folders
.filter(new Predicate<File>() {
#Override
public boolean test(final File o) {
return listOfExtFolders.contains(o.getName()
.toLowerCase());
}
})
.findFirst();
optional.ifPresent(new Consumer<File>() {
#Override
public void accept(final File file) {
thePath[0] = file.getAbsolutePath();
}
});
Log.e("Path", thePath[0]);
try {
ContextCompat.getExternalFilesDirs(context, null);
} catch (Exception e) {
Log.e("PathException", thePath[0]);
}
return thePath[0];
}
P.S. I tested and verified it on a few HTC and Samsung devices.
This function will return the path of SD Card path.
private String getExternalSdCard(){
String finalPath = null;
File sdCardFile = ContextCompat.getExternalFilesDirs(this, null)[1];
String base = String.format("/Android/data/%s/files", getPackageName());
String path = sdCardFile.getAbsolutePath();
if(path.contains(base)){
finalPath = path.replace(base, "");
}
return finalPath;
}
To get all the list of storage. Use Loop
private String[] storages() {
List<String> storages = new ArrayList<>();
try {
File[] externalStorageFiles = ContextCompat.getExternalFilesDirs(this, null);
String base = String.format("/Android/data/%s/files", getPackageName());
for (File file : externalStorageFiles) {
try {
if (file != null) {
String path = file.getAbsolutePath();
if (path.contains(base)) {
String finalPath = path.replace(base, "");
if (validPath(finalPath)) {
storages.add(finalPath);
}
}
}
} catch (Exception e) {
CrashUtils.report(e);
}
}
} catch (Exception e) {
CrashUtils.report(e);
}
String[] result = new String[storages.size()];
storages.toArray(result);
return result;
}
I am searching for a solution to find all folders with the same name in a given directory.
So my folder structure looks like this:
Root
| | |
android windows ios
| | | | | |
focus normal focus normal focus normal
Note: There are more folders between the clients and the iconsets, that's why I need recursion.
I want to get a ArrayList with all the pathes of e.g. Normal folders.
Although recursion confuses me a lot all the time I couldnt to it.
This was my first try, which should return ALL contained directories in the Root folder (parameter path). The String iconset should define the name of the searched folder afterwards.
private static ArrayList<String> getAllIconSetFolders(String path, String iconset) {
ArrayList<String> pathes = new ArrayList<String>();
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
for (File file : listOfFiles) {
if (file != null && file.isDirectory()) {
pathes.addAll(getAllIconSetFolders(file.getAbsolutePath(), iconset));
}
}
return pathes;
}
It will return an empty ArrayList in this case.
How can I get all paths for (The normal folders when String iconset = "normal") so my result would look like:
"Root/android/[...]/normal"
"Root/windows/[...]/normal"
"Root/ios/[...]/normal"
I've just tested the following code and it appears to work correctly:
public static List<File> findDirectoriesWithSameName(String name, File root) {
List<File> result = new ArrayList<>();
for (File file : root.listFiles()) {
if (file.isDirectory()) {
if (file.getName().equals(name)) {
result.add(file);
}
result.addAll(findDirectoriesWithSameName(name, file));
}
}
return result;
}
Your original code was almost there, you just omitted the part where you actually add matching directories to your result list.
Tested with:
C:\tmp\foo
C:\tmp\foo\bar
C:\tmp\foo\baz
C:\tmp\foo\baz\foo
C:\tmp\foo\baz\foo\bar
Using
public static void main(String[] args) throws Exception {
List<File> files = findDirectoriesWithSameName("foo", new File("C:\\tmp"));
for (File f :files) {
System.out.println(f);
}
}
Output:
C:\tmp\foo
C:\tmp\foo\baz\foo
You need to add the directory name to pathes otherwise it will always be empty. Your code should be something like:
private static List<String> getAllIconSetFolders(String path, String iconset)
{
List<String> pathes = new ArrayList<String>();
File folder = new File(path);
for (File file : folder.listFiles())
{
if (file.isDirectory())
{
if (file.getName().equals(iconset))
{
pathes.add(file.getAbsolutePath());
}
else
{
pathes.addAll(getAllIconSetFolders(file.getAbsolutePath(), iconset));
}
}
}
return pathes;
}
This assumes the iconset is the name of the directory you are looking for and that that directories with that name can exist multiple times in the directory tree.
While searching for directory inside a directory, one elegant way is to use FileFilter or for name matching use FileNameFilter. On top of it you apply standard recursive ways the complete solution would be:
static void test()
{
File f = new File("e:\\folder");
List<File> res = new ArrayList<File>();
search(f, res, "normal");
System.out.println(res);
search(f, res, "focus");
System.out.println(res);
}
static void search(File f, List<File> res, final String search)
{
if(f.isDirectory())
{
File[] result = f.listFiles(new FilenameFilter()
{
public boolean accept(File file, String name)
{
return file.isDirectory() && name.equals(search);
}
});
if(result != null)
{
for(File file : result)
{
res.add(file);
}
}
//search further recursively
File[] allFiles = f.listFiles();
if(allFiles != null)
{
for(File file: allFiles)
{
search(file, res, search);
}
}
}
}
Or you can extend FileNameFilter as say NormalDirFilter or FocusDirFilter where you can hardcode specific folder search name. Use instances of these specific filters while listing file during recursion.
Tested. Works. Need Java 7.
public static void main(String[] args) {
List<String> paths = new ArrayList<String>();
getAllFolders("/path/to/folder", "normal", paths);
}
private static void getAllFolders(String path, String folderName, List<String> paths) throws Exception {
Path mainPath = Paths.get(path);
Iterator<Path> stream = Files.newDirectoryStream(mainPath).iterator();
while(stream.hasNext()) {
Path currentPath = stream.next();
String currentFolderName = currentPath.getFileName().toString();
if(currentFolderName.equals(folderName)) {
paths.add(currentPath.toString());
}
getAllFolders(currentPath.toString(), folderName, paths);
}
}
If you have this structure, could you not do
public static List<File> subdirectories(File root, String toFind) {
List<File> ret = new ArrayList<File>();
for(File dir : root.listFiles()) {
File dir2 = new File(dir, toFind);
if (dir2.isDirectory())
ret.add(dir2);
}
return ret;
}