手机SD卡里有很多文件夹,感觉挺乱的,写个代码整理一下吧,就当巩固一下文件操作 封装一下文件夹信息,更方便获取其中的信息,如总大小,文件个数、文件夹个数 很多文件隐藏着,让它暴漏出来,获取空文件夹,然后清理一下空文件夹 自定义文件夹大小的过滤,最后以一个文件夹的浏览器的小案例总结全文。
直接获取文件夹的length()为0,可以通过递归遍历出所有文件夹的文件大小,再累加。
private long dirSize(File dir) {
//遍历文件夹
long size = 0;
for (File file : dir.listFiles()) {
if (file.isFile()) {
size += file.length();
} else {
dirSize(file);
}
}
return size;
}
查看文件夹大小.png
10-26 12:47:34.456 23505-23906/com.toly1994.ti_rp D/SDCardClear: 扫描结束,共40935.586M
DirBean{
path='/storage/emulated/0/DCIM',
name='DCIM',
dirCount=18,
fileCount=2720,
length=2.5565107GB,
modifyTime=2018-10-17 23:16:53
}
/**
* 作者:张风捷特烈<br/>
* 时间:2018/10/26 0026:13:20<br/>
* 邮箱:1981462002@qq.com<br/>
* 说明:文件夹对象
*/
public class DirBean {
private File dir;//文件对象
private String path; //文件路径
private String name;//文件夹名
private int dirCount;//文件夹数量
private int fileCount;//文件的个数
private long length; //文件夹大小
private Long modifyTime;//最后修改时间
public DirBean(File dir) {
if (dir.isFile()) {
return;
}
this.dir = dir;
path = dir.getAbsolutePath();
name = dir.getName();
modifyTime = dir.lastModified();
}
//get、set方法省略...
//格式化后的文件大小
public String getLengthFormated() {
String result = "";
if (length < 1024) {
result = length + "B";
} else if (length < 1024 * 1024) {
result = length / 1024.f + "KB";
L.d(length + "----大小:" + length / 1024.f + "KB");
} else if (length > 1024 * 1024) {
result = length / 1024.f / 1024 + "MB";
}
if (length > 1024 * 1024 * 1024) {
result = length / 1024.f / 1024 / 1024 + "GB";
}
return result;
}
//格式化后的时间
public String getModifyTimeFormated() {
return new SimpleDateFormat("yyyy-MM-dd kk:mm:ss", Locale.CHINA).format(getModifyTime());
}
@Override
public String toString() {
return "DirBean{" +
", path='" + path + '\'' +
", name='" + name + '\'' +
", dirCount=" + dirCount +
", fileCount=" + fileCount +
", length=" + getLengthFormated() +
", modifyTime=" + getModifyTimeFormated() +
'}';
}
}
通过getSizeLocal递归遍历文件夹,由于size、fileCount、dirCount是成员变量,递归中找不到置零时机 如果不置零,对象不死,每次调用都会叠加,这里用一个方法调用getSizeLocal,之后置零
private long size = 0;
private int fileCount = 0;
private int dirCount = 0;
public DirBean getSize(File dir) {
DirBean dirBean = getSizeLocal(dir);
size = 0;
fileCount = 0;
dirCount = 0;
return dirBean;
}
private DirBean getSizeLocal(File dir) {
DirBean dirBean = new DirBean(dir);
//遍历文件夹
for (File file : dir.listFiles()) {
if (file.isFile()) {
fileCount++;
size += file.length();//是文件是长度增加
} else {
dirCount++;
getSizeLocal(file);//不是文件时递归
}
}
dirBean.setLength(size);
dirBean.setFileCount(fileCount);
dirBean.setDirCount(dirCount);
return dirBean;//返回文件夹大小
}
从手机上来看,名称、时间、大小是没问题,经测试,手机上的未显示隐藏的文,所以数目少一些
查看文件夹信息.png
public static long dirListSize(File dir) {
//将size改成局部变量
long size = 0;
for (File file : dir.listFiles()) {
if (file.isFile()) {
size += file.length();
} else {
size = dirListSize(file);
if (size < 1024) {//根据文件夹大小决定采用的单位
L.d(file + "----大小:" + size + "B");
} else if (size < 1024 * 1024) {
L.d(file + "----大小:" + size / 1024.f + "KB");
} else if (size > 1024 * 1024) {
L.d(file + "----大小:" + size / 1024.f / 1024 + "MB");
}
}
}
return size;
}
查看文件夹下所有文件夹大小.png
public long dirListSize(File dir, List<String> list) {
//将size改成局部变量
long size = 0;
for (File file : dir.listFiles()) {
if (file.isFile()) {
size += file.length();
} else {
size = dirListSize(file, list);
if (size < 1024) {//将信息添加到集合
list.add(file + "----大小:" + size + "B");
} else if (size < 1024 * 1024) {
list.add(file + "----大小:" + size / 1024.f + "KB");
} else if (size > 1024 * 1024) {
list.add(file + "----大小:" + size / 1024.f / 1024 + "MB");
}
}
}
return size;
}
/**
* 将文件列表每项的路径保存到目标文件
*
* @param list 列表
* @param target 目标路径
*/
public void writeList2File(List<String> list, String target){
BufferedWriter bfw = null;
try {
bfw = new BufferedWriter(new FileWriter(target));
for (String s : list) {
bfw.write(s);
bfw.newLine();
bfw.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bfw != null) {
bfw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
可见:一共37751个文件夹,每个文件夹大小的路径都保存到文件中了。
将信息保存到文件中.png
/**
* 获取某文件夹下的所有空文件夹
*
* @param dir 根文件夹
* @param list 列表
* @return 大小
*/
public long filterEmptyDir(File dir, List<String> list) {
//将size改成局部变量
long size = 0;
for (File file : dir.listFiles()) {
if (file.isFile()) {
size += file.length();
} else {
size = filterEmptyDir(file, list);
if (size == 0) {
list.add(file.getAbsolutePath());
L.d(file + L.l());
}
}
}
return size;
}
一共8262个空文件夹,比我想象的还要多
空文件夹检测.png
/**
* 删除文件夹里的所有文件
*
* @param dir
*/
public void deleteDir(File dir) {
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
deleteDir(file);
} else {
String name = file.getName();
boolean ok = file.delete();
System.out.println(ok ? "成功删除--" + name : "删除失败--" + name);
}
}
dir.delete();
}
想必应该用过java的比较器,将比较条件向后推延,让用户自定义条件来更灵活控制 拿到空文件夹,拿到大于1000M的文件夹,拿到大小等于32B的文件夹,操作流基本一直,不同的只有比较条件 因此,写一个比较的接口,将实现推迟到用户使用时:
/**
* 作者:张风捷特烈<br/>
* 时间:2018/10/26 0026:16:14<br/>
* 邮箱:1981462002@qq.com<br/>
* 说明:比较接口
*/
public interface ICondition<T> {
/**
* 比较方法接口
* @param param 待比较参数
* @return 是否比较成功
*/
boolean condition(T param);
}
/**
* 根据条件过滤出符合的文件夹
*
* @param dir 根文件夹
* @param list 列表
* @param condition 条件
* @return 大小
*/
public long filterDir(File dir, List<String> list, ICondition<Long> condition) {
//将size改成局部变量
long size = 0;
for (File file : dir.listFiles()) {
if (file.isFile()) {
size += file.length();
} else {
size = filterDir(file, list, condition);
//条件的使用
if (condition.condition(size)) {
list.add(file.getAbsolutePath());
L.d(file + L.l());
}
}
}
return size;
}
List<String> emptyList = new ArrayList<>();
dirHelper.filterDir(rootFile, emptyList, new ICondition<Long>() {
@Override
public boolean condition(Long param) {
//return param == 0;//过滤出空文件夹
return param > 1024 * 1024 * 500;//过滤出大小大于500M的文件夹
}
});
进入时显示SD卡根目录 | 点击文件夹显示内部文件 |
---|
/**
* 格式化文件大小
* @param length 文件长度
* @return 文件大小
*/
public static String formatLong2M(long length) {
String result = "";
if (length < 1024) {
result = length + "B";
} else if (length < 1024 * 1024) {
result = length / 1024.f + "KB";
} else if (length > 1024 * 1024) {
result = length / 1024.f / 1024 + "MB";
}
if (length > 1024 * 1024 * 1024) {
result = length / 1024.f / 1024 / 1024 + "GB";
}
return result;
}
看图写界面应该不麻烦,布局文件太长,就不贴了。
public class SDShowActivity extends AppCompatActivity {
@BindView(R.id.id_lv)
ListView mIdLv;
private File[] mFiles;
private MyLVAdapter<File> mMyAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
//显示ListView
showListView(new File(PathUtils.getSDPath()));
//点击时更新ListView
mIdLv.setOnItemClickListener((parent, view, position, id) -> showListView(mFiles[position]));
}
private void showListView(File file) {
mFiles = file.listFiles();
mMyAdapter = new MyLVAdapter<File>(this, mFiles, R.layout.item_text_only) {
@Override
public void setData(MyLVHolder holder, File data, int position) {
holder.setText(R.id.id_tv_name, data.getName());
holder.setImageViewRes(R.id.id_iv_pic, data.isDirectory() ? R.mipmap.icon_dir : R.mipmap.icon_file);
if (data.isDirectory()) {
holder.setText(R.id.id_tv_size,
StrUtil.formatLong2M(DirHelper.newInstance().getDirBean(data).getLength()));
} else {
holder.setText(R.id.id_tv_size, StrUtil.formatLong2M(file.length()));
}
}
};
mIdLv.setAdapter(mMyAdapter);
}
}
1.非常大的文件加获取大小比较耗时,最好显示文件夹大小时新开线程
2.可以模拟栈来进行返回到上层文件夹的操作,不然就直接退出了
3.可拓展更多的功能点,可以根据文件的后缀名来改变图标
项目源码 | 日期 | 备注 |
---|---|---|
V0.1--无 | 2018-10-26 | 安卓中对于文件夹的综合操作 |
笔名 | 微信 | 爱好 | |
---|---|---|---|
张风捷特烈 | 1981462002 | zdl1994328 | 语言 |
我的github | 我的简书 | 我的CSDN | 个人网站 |
1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持