java.lang.***Error 递归目录
Posted
技术标签:
【中文标题】java.lang.***Error 递归目录【英文标题】:java.lang.***Error Recursive Directory 【发布时间】:2013-05-11 09:09:51 【问题描述】:在我的 android 应用程序中,我将外部存储的所有路径填充到一个数组中。
少数设备报告***Error。
我已阅读 many linked posts 关于此问题的原因,但我不知道如何处理它或防止它在我正在使用的代码中发生。我也不了解 Android 可以处理的“递归限制”。
以下代码改编自from this source。
private final Locale loc = SupportedLanguages.isSupported();
private final String CACHE = "cache";
private final String TEMP = "temp";
@Override
protected Boolean doInBackground(Void... params)
final File fileList = Environment.getExternalStorageDirectory();
final String absolutePath = Environment.getExternalStorageDirectory().getAbsolutePath();
final File[] dirList = fileList.listFiles();
final List<File> listDirs = Arrays.asList(dirList);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
final ArrayList<String> dirPath = new ArrayList<String>();
final ArrayList<String> dirName = new ArrayList<String>();
String fileName = "";
for (final File startingDirectory : listDirs)
if (!startingDirectory.isFile() && startingDirectory.canRead() && !startingDirectory.isHidden())
final List<File> files = getFileListing(startingDirectory);
if (files != null)
for (final File file : files)
fileName = file.getPath().replaceAll(absolutePath, "").toLowerCase(loc).replaceAll("\\/", " ")
.trim();
fileName = fileName.replaceAll(" +", " ");
dirName.add(fileName);
dirPath.add(file.toString());
return true;
private List<File> getFileListing(File aStartingDir)
List<File> result = getFileListingNoSort(aStartingDir);
if (result != null && !result.isEmpty())
Collections.sort(result);
return result;
private List<File> getFileListingNoSort(File aStartingDir)
List<File> resultArray = new ArrayList<File>();
File[] filesAndDirs = aStartingDir.listFiles();
if (filesAndDirs != null && filesAndDirs.length > 0)
List<File> filesDirs = Arrays.asList(filesAndDirs);
for (File file : filesDirs)
if (!file.isFile() && file.canRead() && !file.isHidden() && !file.getName().toLowerCase(loc).startsWith(CACHE)
&& !file.getName().toLowerCase(loc).startsWith(TEMP))
resultArray.add(file);
List<File> deeperList = getFileListingNoSort(file);
resultArray.addAll(deeperList);
return resultArray;
崩溃日志:
> Caused by: java.lang.***Error at
> java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:145)
> at java.lang.StringBuilder.append(StringBuilder.java:216) at
> java.io.File.join(File.java:215) at java.io.File.<init>(File.java:157)
> at java.io.File.<init>(File.java:124) at
> java.io.File.filenamesToFiles(File.java:852) at
> java.io.File.listFiles(File.java:791) at
> com.mypackage.name.ll.a(Unknown Source) at
> com.mypackage.name.ll.a(Unknown Source) at
> com.mypackage.name.ll.a(Unknown Source) at
> com.mypackage.name.ll.a(Unknown Source) at
> com.mypackage.name.ll.a(Unknown Source) at
> com.mypackage.name.ll.a(Unknown Source) at
> com.mypackage.name.ll.a(Unknown Source) at
> com.mypackage.name.ll.a(Unknown Source) at
> com.mypackage.name.ll.a(Unknown Source)
等等……
proguard 映射:
com.mypackage.name.GenerateSubDirectoryList -> com.mypackage.name.ll:
java.util.List getFileListingNoSort(java.io.File) -> a
我需要在某个地方计算递归并应用限制。但我不知道适用于 Android 或单个设备硬件的位置或限制?
提前感谢您的帮助。
【问题讨论】:
【参考方案1】:计算递归很容易:只需将int
参数添加到getFileListingNoSort
方法并在每次调用时递增值:
private List<File> getFileListingNoSort(File aStartingDir, int level)
List<File> resultArray = new ArrayList<File>();
File[] filesAndDirs = aStartingDir.listFiles();
if (level < MAX_LEVEL && filesAndDirs != null && filesAndDirs.length > 0)
List<File> filesDirs = Arrays.asList(filesAndDirs);
for (File file : filesDirs)
if (!file.isFile() && file.canRead() && !file.isHidden() && !file.getName().toLowerCase(loc).startsWith(CACHE)
&& !file.getName().toLowerCase(loc).startsWith(TEMP))
resultArray.add(file);
List<File> deeperList = getFileListingNoSort(file, ++level);
resultArray.addAll(deeperList);
return resultArray;
但问题仍然存在:MAX_LEVEL 的最佳值是多少?为什么它会无限循环。有问题的文件系统可能具有创建循环的符号链接。
【讨论】:
谢谢安德烈亚斯。是的,问题仍然是这个限制应该设置为多少?此外,我还看到了超出“最大整数级别”并且应该使用 long 的帖子。不知道限制,我不知道这是否也需要考虑?不太可能是因为计数是存储路径。感谢您指出符号链接-我没有考虑过。我会调查的。【参考方案2】:Android 在很多硬件上运行,其中很多可能根本没有太多堆栈;而不是通过子目录递归,进行广度优先搜索,因此:
private List<File> getFileListingNoSort(File aStartingDir)
// assuming aStartingDir is a valid input
List<File> dirsToSearch = new ArrayList<File>();
dirsToSearch.add(aStartingDir);
List<File> resultArray = new ArrayList<File>();
do
File thisDir = dirsToSearch.remove(0);
List<File> filesDirs = Arrays.asList(thisDir.listFiles());
for (File file : filesDirs)
if (file.isDirectory())
dirsToSearch.add(file);
else if( file.canRead() &&
!file.isHidden() &&
!file.getName().toLowerCase(loc).startsWith(CACHE) &&
!file.getName().toLowerCase(loc).startsWith(TEMP))
resultArray.add(file);
while(false == dirsToSearch.isEmpty());
return resultArray;
请注意:我没有运行,甚至没有查看此代码是否编译。
但想法是,维护一个目录列表,从您关心的目录开始,从该列表中删除第一个目录,将该目录中的文件添加到结果中(修改代码以将目录添加到resultArray 如果你也想要目录),将目录添加到要搜索的目录列表中,并继续直到目录列表为空。
如果你不能提前知道你必须递归多远,或者你能走多远,那么递归就是不好的。我不认为文件系统迭代是递归的合适位置,但这是我自己的观点。
【讨论】:
谢谢 Ben,但我有点困惑 - '维护目录列表' 当你在遍历 filesDirs 的过程中遇到一个目录时,你将它添加到 dirsToSearch;否则,您检查它是否满足您的条件,如果满足,请将其添加到 resultsArray。只要有您已添加但未列出的目录,do...while 循环就会继续,列出目录的第一步是将其从 dirsToSearch 中删除。 我需要一点时间来消化您建议的实现。感谢您回来澄清。以上是关于java.lang.***Error 递归目录的主要内容,如果未能解决你的问题,请参考以下文章
为啥布尔 DBHelper.updateStudents(java.lang.String,java.lang.String,java.lang.String,java.lang.String, ja
如何解决 java.lang.NoClassDefFoundError: javax/annotation/Generated?
Caused by: java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut aaa(示