0. 前言
今天有个需求,把Android中data/data目录下指定(通过读预置的XML文件)的多个应用下的多个目录全部内容通过OTG模式复制到U盘中。
首先读取XML文件内的某个节点的属性值,这个已经在Java实现——Dom4j读写XML文件中详细介绍过了。
那么毋庸置疑第一步就是理清如何将一个文件夹内的全部内容一起复制到指定的新的文件夹下。
后面这个FileUtils工具类类可以完全满足需求,在此分享出来方便大家使用。
参数为源目录以及目标目录的File对象实例。
1. 字符串分割
1.1 使用split
第一步就是将字符串根据分号切分,这个使用split比较容易,代码分别总结如下。
String str = "com.tencent.mm/MicroMsg;com.tencent.mm/shared_prefs" ; String[] temp = str.split(";"); System.out.println(Arrays.toString(temp));
同时,若不止通过分号进行分割,如需要根据逗号和分号一起分割,那么改变split内的参数即可。
String[] temp = str.split(",|;");
1.2 使用StringTokenizer
文档上表示使用StringTokenizer性能会比split更高,这里介绍一下StringTokenizer的用法,也比较简单。
1.2.1 第一种构造方法
//构造一个用来解析str的StringTokenizer对象 //Java默认的分隔符是“空格”“制表符(‘ ’)”“换行符(‘ ’)”“回车符(‘ ’)” StringTokenizer(String str)这种构造函数的使用示例如下:
String s=new String("SEU Calvin is handsome"); StringTokenizer st=new StringTokenizer(s); System.out.println("Token Total:"+st.countTokens());//返回nextToken()被调用的次数 while ( st.hasMoreElements() ){ //判断是否还有分隔符 System.out.println(st.nextToken());//nextToken返回分隔后的各个子字符串输出结果为:
Token Total:4 SEU Calvin is handsome
//构造一个用来解析str的StringTokenizer对象 //并提供一个指定的分隔符 //同时,指定是否返回分隔符,如果不提供boolean默认为false StringTokenizer(String str,String delim,boolean returnDelims)这种构造函数的使用示例如下:
String s=new String("SEU=Calvin=is=handsome"); StringTokenizer st=new StringTokenizer(s,"=",true); System.out.println("Token Total:"+st.countTokens()); while ( st.hasMoreElements() ){ System.out.println(st.nextToken());输出结果为:
Token Total:7 SEU = Calvin = is = handsome若第三个参数修改为false,或根本不带第三个参数,因为默认为false,则输出如下:
Token Total:4 SEU Calvin is handsome
2. 文件拷贝工具类
FileUtils工具类展示如下:
import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; public class FileUtils { private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; public static void copyDirectory(File srcDir, File destDir) throws IOException { copyDirectory(srcDir, destDir, true); } public static void copyDirectory(File srcDir, File destDir, boolean preserveFileDate) throws IOException { copyDirectory(srcDir, destDir, null, preserveFileDate); } public static void copyDirectory(File srcDir, File destDir, FileFilter filter) throws IOException { copyDirectory(srcDir, destDir, filter, true); } public static void copyDirectory(File srcDir, File destDir, FileFilter filter, boolean preserveFileDate) throws IOException { if (srcDir == null) { throw new NullPointerException("Source must not be null"); } if (destDir == null) { throw new NullPointerException("Destination must not be null"); } if (srcDir.exists() == false) { throw new FileNotFoundException("Source '" + srcDir + "' does not exist"); } if (srcDir.isDirectory() == false) { throw new IOException("Source '" + srcDir + "' exists but is not a directory"); } if (srcDir.getCanonicalPath().equals(destDir.getCanonicalPath())) { throw new IOException("Source '" + srcDir + "' and destination '" + destDir + "' are the same"); } // Cater for destination being directory within the source directory // (see IO-141) List exclusionList = null; if (destDir.getCanonicalPath().startsWith(srcDir.getCanonicalPath())) { File[] srcFiles = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter); if (srcFiles != null && srcFiles.length > 0) { exclusionList = new ArrayList(srcFiles.length); for (int i = 0; i < srcFiles.length; i++) { File copiedFile = new File(destDir, srcFiles[i].getName()); exclusionList.add(copiedFile.getCanonicalPath()); } } } doCopyDirectory(srcDir, destDir, filter, preserveFileDate, exclusionList); } private static void doCopyDirectory(File srcDir, File destDir, FileFilter filter, boolean preserveFileDate, List exclusionList) throws IOException { if (destDir.exists()) { if (destDir.isDirectory() == false) { throw new IOException("Destination '" + destDir + "' exists but is not a directory"); } } else { if (destDir.mkdirs() == false) { throw new IOException("Destination '" + destDir + "' directory cannot be created"); } if (preserveFileDate) { destDir.setLastModified(srcDir.lastModified()); } } if (destDir.canWrite() == false) { throw new IOException("Destination '" + destDir + "' cannot be written to"); } // recurse File[] files = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter); if (files == null) { // null if security restricted throw new IOException("Failed to list contents of " + srcDir); } for (int i = 0; i < files.length; i++) { File copiedFile = new File(destDir, files[i].getName()); if (exclusionList == null || !exclusionList.contains(files[i].getCanonicalPath())) { if (files[i].isDirectory()) { doCopyDirectory(files[i], copiedFile, filter, preserveFileDate, exclusionList); } else { doCopyFile(files[i], copiedFile, preserveFileDate); } } } } private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException { if (destFile.exists() && destFile.isDirectory()) { throw new IOException("Destination '" + destFile + "' exists but is a directory"); } FileInputStream input = new FileInputStream(srcFile); try { FileOutputStream output = new FileOutputStream(destFile); try { copy(input, output); } finally { try { output.close(); } catch (IOException ioe) { // do nothing } } } finally { try { input.close(); } catch (IOException ioe) { // do nothing } } if (srcFile.length() != destFile.length()) { throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'"); } if (preserveFileDate) { destFile.setLastModified(srcFile.lastModified()); } } // 测试出要复制的文件数量 public static int copy(InputStream input, OutputStream output) throws IOException { long count = copyLarge(input, output); if (count > Integer.MAX_VALUE) { return -1; } return (int) count; } // 复制大文件 public static long copyLarge(InputStream input, OutputStream output) throws IOException { byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; long count = 0; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return count; } }