关于File的处理,文件,目录的创建和删除,都需要添加对storage的读写权限。
Android6.0以后,加强了对权限的管理功能,除在Manifest添加权限外,还需要用户同意勾选赋予权限呢。
写了一个FileClass,添加了一些常用的方法,还有很多,没有添加的,暂时先这样了。
package com.hjk.shiny.androidcontrols;
import android.content.Context;
import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.channels.FileChannel;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* Created by Maibenben on 2018/2/2.
*/
/**
* 需要添加的权限
* 在SDCard中创建与删除文件权限
* <uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
* 往SDCard写入数据权限
* <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
*/
/**
* File常用方法:
* 建立文件
* File.createNewFile();
*
* 建立文件夹
* File.mkDir();
*
* 判断是否是文件
* File.isFile();
*
* 判断是否是文件夹
* File.isDirectory();
*
* 列出文件夹下的所有文件和文件夹名
* File[] files = File.listFiles();
*
* //重命名文件或文件夹
* File.renameTo(dest);
*
* //删除文件夹或文件
* File.delete();
*
* //获得文件或文件夹的名称
* String Name = File.getName();
*
* //获得文件或文件夹的父目录
* String parentPath = File.getParent();
*
* //获得文件或文件夹的绝对路经
* String path = File.getAbsoultePath();
*
* //获得文件或文件夹的路经
* String path = File.getPath();
*
* //获得sd卡根目录
* File skRoot = Environment.getExternalStorageDirectory();
*/
/**
* StatFs用于获取存储空间
*构造函数:StatFs(String path){}
*
* API>18时的方法
*
* 文件系统中可被应用程序使用的空闲存储区块的数量
* getAvailableBlocksLong()
*
* 文件系统中可被应用程序使用的空闲字节数
* getAvailableBytes()
*
* 文件系统中总的存储区块的数量
* getBlockCountLong()
*
* 文件系统中每个存储区块的字节数
* getBlockSizeLong()
*
* 文件系统中总的空闲存储区块的数量,包括保留的存储区块(不能被普通应用程序使用)
* getFreeBlocksLong()
*
* 文件系统中总的空闲字节数,包括保留的存储区块(不能被普通应用程序使用)
* getFreeBytes()
*
* 文件系统支持的总的存储字节数
* getTotalBytes()
*/
/**
* fileChannel
* 它能直接连接输入输出流的文件通道,将数据直接写入到目标文件中去,而且效率更高。
* FileChannel是一个用读写,映射和操作一个文件的通道。
* 除读写操作之外,还有裁剪特定大小文件truncate(),
* 强制在内存中的数据刷新到硬盘中去force(),
* 对通道上锁lock()等功能。
*/
public class FileClass {
/**
* 判断sd卡是否挂载
*/
public static boolean isSDcardMount() {
//Environment.MEDIA_MOUNTED => "mounted","unmounted"
boolean result = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
return result;
}
/**
* 获取sdcard根目录
*/
public static String getSDcardBaseDir() {
//调用前需先判断sdcard是否挂载
String result = Environment.getExternalStorageDirectory().getAbsolutePath();
return result;
}
/**
* 获取sdcard大小
*/
public static long getSDcardAllSizeKb() {
long result = 0;
//获取sdcard当前相对路径
String filepath = Environment.getExternalStorageDirectory().getPath();
//获取sdcard总大小/1024转换为kb单位
StatFs sf = new StatFs(filepath);
result = sf.getTotalBytes() / 1024;
return result;
}
/**
* 获取sdcard当前可用空间
*/
public static long getSDcardAvaliableSizeKb() {
long result = 0;
String filePath = Environment.getExternalStorageDirectory().getPath();
StatFs sf = new StatFs(filePath);
//获取系统中可被应用程序使用的字节转为kb
result = sf.getAvailableBytes() / 1024;
return result;
}
/**
* 获取文件或目录的大小
*/
public static long getFileSize(File file) {
long result = 0;
//判断file是否存在
if (file.exists()) {
//判断目录还是文件
if (file.isDirectory()) {
//遍历目录所有内容
for (File inFile : file.listFiles()) {
//递归读大小
result += getFileSize(inFile);
}
} else {
result += file.length();
}
} else {
throw new IllegalArgumentException("file does not exists!");
}
return result;
}
/**
* 清空文件或目录
* true:clear
* false:delete
*/
public static void clearOrDeleteFile(File file, boolean clearOrDelete) {
//先判断存在
if(file.exists()) {
//再判断类型
if (file.isDirectory()) {
//清空删除前面的步骤相同,不同于是否留下最外层目录
for (File inFile : file.listFiles()) {
clearOrDeleteFile(inFile, false);
}
//判断清空还是删除
if (!clearOrDelete) {
//删除则去除最外层目录
file.delete();
}
} else {
//判断清空还是删除
if (clearOrDelete) {
String path = file.getPath();
file.delete();
File newFile = new File(path);
//异常捕获---file删除失败情况下
try {
newFile.createNewFile();
} catch (IOException e) {
System.out.println("file delete fail in clear");
e.printStackTrace();
}
} else {
//删除
file.deleteOnExit();
}
}
}else{
throw new IllegalArgumentException("file does not exists");
}
}
/**
*File 复制
*/
public static boolean copyFile(String srcPath,String dstPath){
boolean result=false;
//判断参数
if(srcPath==null||dstPath==null){
return result;
}
File srcFile=new File(srcPath);
File dstFile=new File(dstPath);
FileChannel srcChannel=null;
FileChannel dstChannel=null;
//链接输入输出管道
try {
srcChannel=new FileInputStream(srcFile).getChannel();
dstChannel=new FileOutputStream(dstFile).getChannel();
//数据复制
srcChannel.transferTo(0,srcChannel.size(),dstChannel);
result=true;
} catch (FileNotFoundException e) {
System.out.println("exception in file not found");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
System.out.println("exception in io");
}
return result;
}
/**
* 将String写入file
*/
public static boolean saveStringToFile(String content,String filePath){
boolean result=false;
//content可以为“”不可以为null,filePath不能为空
if(content==null|| TextUtils.isEmpty(filePath)){
return result;
}
File file=new File(filePath);
PrintWriter pw=null;
//判断file是否存在,不存在新建
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
System.out.println("file create exception!");
e.printStackTrace();
}
}
//实例化printwrite,使用完close
try {
pw=new PrintWriter(file);
pw.write(content);
result=true;
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if(pw!=null){
pw.close();
}
}
return result;
}
/**
* 读取file内容
*/
public static String readStringFromFile(String filePath){
String result="";
if(TextUtils.isEmpty(filePath)){
return result;
}
File file=new File(filePath);
if(file.exists()){
try {
StringBuffer sb=new StringBuffer();
BufferedReader reader=new BufferedReader(new FileReader(file));
while((result=reader.readLine())!=null){
sb.append(result);
}
return sb.toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
/**
* 递归解压Zip
* 针对zip下可能含有目录及目录下还有子目录和文件的情况
* zipFileString 压缩文件字符串
* folderPath 解压到的目标路径
*/
public static boolean unpackZipFile(String zipFileString,String folderPath){
boolean result =false;
ZipFile zipFile=null;
try {
zipFile=new ZipFile(zipFileString);
} catch (IOException e) {
e.printStackTrace();
}
//获取zipFile压缩文件中的所有元素集,并遍历,包括了目录下的目录和文件
Enumeration zList=zipFile.entries();
ZipEntry ze=null;
byte[]bytes=new byte[1024];
while (zList.hasMoreElements()){
ze= (ZipEntry) zList.nextElement();
//列举压缩文件中每个元素并进行判断文件还是目录
if(ze.isDirectory()){//目录
//新路径
String dirstr=folderPath+ze.getName();
//去空格
dirstr.trim();
//建目录
File dirFile=new File(dirstr);
dirFile.mkdir();
//此轮完进入下一轮
continue;
}
//如果ze是文件
OutputStream os=null;
FileOutputStream fos=null;
File realFile=getRealFileName(folderPath,ze.getName());
try {
fos=new FileOutputStream(realFile);
os=new BufferedOutputStream(fos);
InputStream is=null;
is=new BufferedInputStream(zipFile.getInputStream(ze));
int readLine=0;
while((readLine=is.read(bytes,0,1024))!=-1){
os.write(bytes,0,readLine);
}
is.close();
os.close();
zipFile.close();
result=true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
/**
* 从Zip的getName中获取系统可识别的路径名
* filepath 解压到的目标路径
* zipName 通过zipentry.getname获得的zipname
*/
public static File getRealFileName(String filePath,String zipName){
//先替换掉双斜杠,磁盘路径带有\\
zipName=zipName.replace("\\","/");
//按照单斜杠切分
String[]dirs=zipName.split("/");
//根据路径创建文件实例
File file=new File(filePath);
String subStr="";
if(dirs.length>1){
//dirs.length-1前面的都是目录,dirs.length-1是文件
for(int i=0;i<dirs.length-1;i++){
subStr=dirs[i];
File subFile=new File(file,subStr);
}
//路径上的目录不全就makdir补全目录,再创建文件
if(file.exists()){
file.mkdir();
subStr=dirs[dirs.length-1];
file=new File(file,subStr);
return file;
}
}else{
file=new File(file,zipName);
}
return file;
}
/**
* 压缩文件为zip
* fs 需要压缩的文件集
* zipFilePath 指定压缩文件的存储目录
*/
public static boolean zipFiles(File[]fs,String zipFilePath){
Boolean result=false;
//判空
if(fs==null){
return result;
}
ZipOutputStream zos=null;
try {
//zip输出流
zos=new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFilePath)));
for(File file:fs){
//对需要压缩的文件检查一遍
if(file==null||!file.exists()){
continue;
}
//所有的压缩代码放置于recursionZip中
if(file.isDirectory()){
recursionZip(zos, file, file.getName() + File.separator);
}else{
recursionZip(zos,file,"");
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return result;
}
/**
* 递归热cursion压缩目录
*zipout 压缩输出流
* file 被压缩的文件
* baseDir 压缩路径
*/
public static void recursionZip(ZipOutputStream zipOut,File file,String baseDir){
//判断file的类型
if(file.isDirectory()){
File[]files=file.listFiles();
for(File inFile:files){
if(inFile==null){
continue;
}
if(inFile.isDirectory())
baseDir = file.getName() + File.separator + inFile.getName() + File.separator;
recursionZip(zipOut,inFile,baseDir);
}
}else{
byte[]buf=new byte[1024];
try {
InputStream is=new BufferedInputStream(new FileInputStream(file));
zipOut.putNextEntry(new ZipEntry(baseDir+file.getName()));
int readLine=0;
while((readLine=is.read(buf))!=-1){
zipOut.write(buf,0,readLine);
}
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}