package com.saicfc.saicifx3.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; 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.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.RandomAccessFile; import java.io.StringReader; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveStreamFactory; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.saicfc.saicifx3.vo.FileInfo; /** * 文件辅助类 * * @author ShenHuaJie * @since 2012-03-22 */ public class FileUtils { private static Log log = LogFactory.getLog(FileUtils.class); private static int BUF = 1024; private static String encoding = "GBK"; /** * 单个文件拷贝。 * * @param srcFile * @param destFile * @param overwrite * 是否覆盖目的文件 * @throws IOException */ public static void copyFile(File srcFile, File destFile, boolean overwrite) throws IOException { // 首先判断源文件是否存在 if (!srcFile.exists()) { throw new FileNotFoundException("Cannot find the source file: " + srcFile.getAbsolutePath()); } // 判断源文件是否可读 if (!srcFile.canRead()) { throw new IOException("Cannot read the source file: " + srcFile.getAbsolutePath()); } if (overwrite == false) { // 目标文件存在就不覆盖 if (destFile.exists()) return; } else { // 如果要覆盖已经存在的目标文件,首先判断是否目标文件可写。 if (destFile.exists()) { if (!destFile.canWrite()) { throw new IOException("Cannot write the destination file: " + destFile.getAbsolutePath()); } } else { // 不存在就创建一个新的空文件。 if (!destFile.createNewFile()) { throw new IOException("Cannot write the destination file: " + destFile.getAbsolutePath()); } } } BufferedInputStream inputStream = null; BufferedOutputStream outputStream = null; byte[] block = new byte[1024]; try { inputStream = new BufferedInputStream(new FileInputStream(srcFile)); outputStream = new BufferedOutputStream(new FileOutputStream(destFile)); while (true) { int readLength = inputStream.read(block); if (readLength == -1) break;// end of file outputStream.write(block, 0, readLength); } } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException ex) { // just ignore } } if (outputStream != null) { try { outputStream.close(); } catch (IOException ex) { // just ignore } } } } /** * 单个文件拷贝。 * * @param srcFilename * @param destFilename * @param overwrite * @throws IOException */ public static void copyFile(String srcFilename, String destFilename, boolean overwrite) throws IOException { File srcFile = new File(srcFilename); // 首先判断源文件是否存在 if (!srcFile.exists()) { throw new FileNotFoundException("Cannot find the source file: " + srcFile.getAbsolutePath()); } // 判断源文件是否可读 if (!srcFile.canRead()) { throw new IOException("Cannot read the source file: " + srcFile.getAbsolutePath()); } File destFile = new File(destFilename); if (overwrite == false) { // 目标文件存在就不覆盖 if (destFile.exists()) return; } else { // 如果要覆盖已经存在的目标文件,首先判断是否目标文件可写。 if (destFile.exists()) { if (!destFile.canWrite()) { throw new IOException("Cannot write the destination file: " + destFile.getAbsolutePath()); } } else { // 不存在就创建一个新的空文件。 if (!destFile.createNewFile()) { throw new IOException("Cannot write the destination file: " + destFile.getAbsolutePath()); } } } BufferedInputStream inputStream = null; BufferedOutputStream outputStream = null; byte[] block = new byte[1024]; try { inputStream = new BufferedInputStream(new FileInputStream(srcFile)); outputStream = new BufferedOutputStream(new FileOutputStream(destFile)); while (true) { int readLength = inputStream.read(block); if (readLength == -1) break;// end of file outputStream.write(block, 0, readLength); } } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException ex) { // just ignore } } if (outputStream != null) { try { outputStream.close(); } catch (IOException ex) { // just ignore } } } } /** * 拷贝文件,从源文件夹拷贝文件到目的文件夹。 <br> * 参数源文件夹和目的文件夹,最后都不要带文件路径符号,例如:c:/aa正确,c:/aa/错误。 * * @param srcDirName * 源文件夹名称 ,例如:c:/test/aa 或者c:\\test\\aa * @param destDirName * 目的文件夹名称,例如:c:/test/aa 或者c:\\test\\aa * @param overwrite * 是否覆盖目的文件夹下面的文件。 * @throws IOException */ public static void copyFiles(String srcDirName, String destDirName, boolean overwrite) throws IOException { File srcDir = new File(srcDirName);// 声明源文件夹 // 首先判断源文件夹是否存在 if (!srcDir.exists()) { throw new FileNotFoundException("Cannot find the source directory: " + srcDir.getAbsolutePath()); } File destDir = new File(destDirName); if (overwrite == false) { if (destDir.exists()) { // do nothing } else { if (destDir.mkdirs() == false) { throw new IOException("Cannot create the destination directories = " + destDir); } } } else { // 覆盖存在的目的文件夹 if (destDir.exists()) { // do nothing } else { // create a new directory if (destDir.mkdirs() == false) { throw new IOException("Cannot create the destination directories = " + destDir); } } } // 循环查找源文件夹目录下面的文件(屏蔽子文件夹),然后将其拷贝到指定的目的文件夹下面。 File[] srcFiles = srcDir.listFiles(); if (srcFiles == null || srcFiles.length < 1) { // throw new IOException ("Cannot find any file from source // directory!!!"); return;// do nothing } // 开始复制文件 int SRCLEN = srcFiles.length; for (int i = 0; i < SRCLEN; i++) { // File tempSrcFile = srcFiles[i]; File destFile = new File(destDirName + File.separator + srcFiles[i].getName()); // 注意构造文件对象时候,文件名字符串中不能包含文件路径分隔符";". // log.debug(destFile); if (srcFiles[i].isFile()) { copyFile(srcFiles[i], destFile, overwrite); } else { // 在这里进行递归调用,就可以实现子文件夹的拷贝 copyFiles(srcFiles[i].getAbsolutePath(), destDirName + File.separator + srcFiles[i].getName(), overwrite); } } } /** * 创建单个文件夹。 * * @param dir * @param ignoreIfExitst * true 表示如果文件夹存在就不再创建了。false是重新创建。 * @throws IOException */ public static void createDir(String dir, boolean ignoreIfExitst) throws IOException { File file = new File(dir); if (ignoreIfExitst && file.exists()) { return; } if (file.mkdir() == false) { throw new IOException("Cannot create the directory = " + dir); } } /** * 创建多个文件夹 * * @param dir * @param ignoreIfExitst * @throws IOException */ public static void createDirs(String dir, boolean ignoreIfExitst) throws IOException { File file = new File(dir); if (ignoreIfExitst && file.exists()) { return; } if (file.mkdirs() == false) { throw new IOException("Cannot create directories = " + dir); } } /** * 删除文件夹及其下面的子文件夹 * * @param dir * @throws IOException */ public static void deleteDir(File dir) throws IOException { if (dir.isFile()) throw new IOException("IOException -> BadInputException: not a directory."); File[] files = dir.listFiles(); if (files != null) { for (int i = 0; i < files.length; i++) { File file = files[i]; if (file.isFile()) { file.delete(); } else { deleteDir(file); } } }// if dir.delete(); } /** * 删除一个文件。 * * @param filename * @throws IOException */ public static void deleteFile(String filename) throws IOException { File file = new File(filename); log.trace("Delete file = " + filename); if (file.isDirectory()) { throw new IOException("IOException -> BadInputException: not a file."); } if (file.exists() == false) { throw new IOException("IOException -> BadInputException: file is not exist."); } if (file.delete() == false) { throw new IOException("Cannot delete file. filename = " + filename); } } /** * 解压缩 * * @param srcPath * @param toPath * @throws IOException * @throws ArchiveException */ public static void doUnZip(String srcPath, String toPath) throws IOException, ArchiveException { ZipFile file = new ZipFile(srcPath, encoding); Enumeration<ZipArchiveEntry> en = file.getEntries(); ZipArchiveEntry ze; while (en.hasMoreElements()) { ze = en.nextElement(); File f = new File(toPath, ze.getName());// 创建完整路径 if (ze.isDirectory()) { f.mkdirs(); continue; } else f.getParentFile().mkdirs(); InputStream is = file.getInputStream(ze); OutputStream os = new FileOutputStream(f); IOUtils.copy(is, os, BUF); is.close(); os.close(); } file.close(); } /** * 压缩文件或文件夹 * * @param files * @param toPath * @throws ArchiveException * @throws IOException */ public static void doZip(List<File> files, String toPath) throws ArchiveException, IOException { // or new ZipArchiveOutputStream(new FileOutputStream(path)) ZipArchiveOutputStream zos = (ZipArchiveOutputStream) new ArchiveStreamFactory() .createArchiveOutputStream("zip", new FileOutputStream(toPath)); zos.setEncoding(encoding); ZipArchiveEntry ze; for (File file : files) { if (!file.exists()) continue; ze = new ZipArchiveEntry(getEntryName(file, null));// 获取每个文件相对路径,作为在ZIP中路径 zos.putArchiveEntry(ze); // folder if (ze.isDirectory()) { zos.closeArchiveEntry(); continue; } // file FileInputStream fis = new FileInputStream(file); IOUtils.copy(fis, zos, BUF); fis.close(); zos.closeArchiveEntry(); } zos.close(); } /** * 将文件清空。 * * @param srcFilename * @throws IOException */ public static void emptyFile(String srcFilename) throws IOException { File srcFile = new File(srcFilename); if (!srcFile.exists()) { throw new FileNotFoundException("Cannot find the file: " + srcFile.getAbsolutePath()); } if (!srcFile.canWrite()) { throw new IOException("Cannot write the file: " + srcFile.getAbsolutePath()); } FileOutputStream outputStream = new FileOutputStream(srcFilename); outputStream.close(); } /** * 获取到目录下面文件的大小。包含了子目录。 * * @param dir * @return * @throws IOException */ public static long getDirLength(File dir) throws IOException { if (dir.isFile()) throw new IOException("BadInputException: not a directory."); long size = 0; File[] files = dir.listFiles(); if (files != null) { for (int i = 0; i < files.length; i++) { File file = files[i]; // file.getName(); // System.out.println(file.getName()); long length = 0; if (file.isFile()) { length = file.length(); } else { length = getDirLength(file); } size += length; }// for }// if return size; } /** * 以行为单位读取文件,读取行数记录 * * @param fileName * @return * @throws IOException */ public static int getFileLineNumber(String fileName) throws IOException { File file = new File(fileName); BufferedReader reader = null; int line = 0; try { reader = new BufferedReader(new FileReader(file)); // 一次读入一行,直到读入null为文件结束 while (reader.readLine() != null) { line++;// 显示行号 } } finally { if (reader != null) { reader.close(); } } return line; } /** * 列出指定文件目录下面的文件信息。 * * @param dir * @return * @throws IOException */ public static List<FileInfo> getFiles(File dir) throws IOException { if (dir.isFile()) throw new IOException("BadInputException: not a directory."); if (!dir.exists()) { throw new IOException(" don't exist "); } File[] files = dir.listFiles(); int LEN = 0; if (files != null) { LEN = files.length; } List<FileInfo> l = new ArrayList<FileInfo>(); long tempFLen = 0; // 文件长度 for (int i = 0; i < LEN; i++) { FileInfo temp = new FileInfo(); temp.setFileName(files[i].getName()); temp.setIsDir(files[i].isDirectory()); // 是文件,且包含. if (files[i].isFile()) { if (files[i].getName().lastIndexOf(".") != -1) temp.setFileType(files[i].getName().substring( files[i].getName().lastIndexOf("."))); } else { temp.setFileType("文件夹"); } tempFLen = files[i].length(); temp.setFileLength(tempFLen); if (tempFLen / 1024 / 1024 / 1024 > 0) { temp.setFileSize(files[i].length() / 1024 / 1024 / 1024 + "G"); } else if (tempFLen / 1024 / 1024 > 0) { temp.setFileSize(files[i].length() / 1024 / 1024 + "M"); } else if (tempFLen / 1024 > 0) { temp.setFileSize(files[i].length() / 1024 + "K"); } else { temp.setFileSize(tempFLen + "byte"); } temp.setFilePath(files[i].getAbsolutePath().replaceAll("[\\\\]", "/")); temp.setLastModified(DateUtil.getDateFromLong(files[i].lastModified())); temp.setIsHidden(files[i].isHidden()); temp.setAuthor(null); temp.setVersion(null); temp.setFileClass(null); temp.setRemark(null); l.add(temp); } return l; } public static String getFileSeparator() { return java.io.File.separator; } /* * 1 ABC 2 abC Gia su doc tu dong 1 lay ca thay 5 dong => 1 --> 5 3 ABC */ public static String[] getLastLines(File file, int linesToReturn) throws IOException, FileNotFoundException { final int AVERAGE_CHARS_PER_LINE = 250; final int BYTES_PER_CHAR = 2; RandomAccessFile randomAccessFile = null; StringBuffer buffer = new StringBuffer(linesToReturn * AVERAGE_CHARS_PER_LINE); int lineTotal = 0; try { randomAccessFile = new RandomAccessFile(file, "r"); long byteTotal = randomAccessFile.length(); long byteEstimateToRead = linesToReturn * AVERAGE_CHARS_PER_LINE * BYTES_PER_CHAR; long offset = byteTotal - byteEstimateToRead; if (offset < 0) { offset = 0; } randomAccessFile.seek(offset); // log.debug("SKIP IS ::" + offset); String line = null; String lineUTF8 = null; while ((line = randomAccessFile.readLine()) != null) { lineUTF8 = new String(line.getBytes("ISO8859_1"), "UTF-8"); lineTotal++; buffer.append(lineUTF8).append("\n"); } } finally { if (randomAccessFile != null) { try { randomAccessFile.close(); } catch (IOException ex) { } } } String[] resultLines = new String[linesToReturn]; BufferedReader in = null; try { in = new BufferedReader(new StringReader(buffer.toString())); int start = lineTotal /* + 2 */- linesToReturn; // Ex : 55 - 10 = 45 // ~ offset if (start < 0) start = 0; // not start line for (int i = 0; i < start; i++) { in.readLine(); // loop until the offset. Ex: loop 0, 1 ~~ 2 // lines } int i = 0; String line = null; while ((line = in.readLine()) != null) { resultLines[i] = line; i++; } } catch (IOException ie) { log.error("Error" + ie); throw ie; } finally { if (in != null) { try { in.close(); } catch (IOException ex) { } } } return resultLines; } public static String getPathSeparator() { return java.io.File.pathSeparator; } /** * 读取文件的内容,并将文件内容以字符串的形式返回。 * * @param fileName * @param srcEncoding * @return * @throws FileNotFoundException * @throws IOException */ public static String readFile(String fileName, String srcEncoding) throws FileNotFoundException, IOException { File file = null; try { file = new File(fileName); if (file.isFile() == false) { throw new IOException("'" + fileName + "' is not a file."); } } finally { // we dont have to close File here } BufferedReader reader = null; try { StringBuffer result = new StringBuffer(1024); FileInputStream fis = new FileInputStream(fileName); reader = new BufferedReader(new InputStreamReader(fis, srcEncoding)); char[] block = new char[512]; while (true) { int readLength = reader.read(block); if (readLength == -1) break;// end of file result.append(block, 0, readLength); } return result.toString(); } catch (FileNotFoundException fe) { log.error("Error", fe); throw fe; } catch (IOException e) { log.error("Error", e); throw e; } finally { try { if (reader != null) reader.close(); } catch (IOException ex) { } } } /** * Write content to a fileName with the destEncoding 写文件。如果此文件不存在就创建一个。 * * @param content * String * @param fileName * String * @param destEncoding * String * @throws FileNotFoundException * @throws IOException */ public static void writeFile(String content, String fileName, String destEncoding) throws FileNotFoundException, IOException { File file = null; try { file = new File(fileName); if (!file.exists()) { if (file.createNewFile() == false) { throw new IOException("create file '" + fileName + "' failure."); } } if (file.isFile() == false) { throw new IOException("'" + fileName + "' is not a file."); } if (file.canWrite() == false) { throw new IOException("'" + fileName + "' is a read-only file."); } } finally { // we dont have to close File here } BufferedWriter out = null; try { FileOutputStream fos = new FileOutputStream(fileName); out = new BufferedWriter(new OutputStreamWriter(fos, destEncoding)); out.write(content); out.flush(); } catch (FileNotFoundException fe) { log.error("Error", fe); throw fe; } catch (IOException e) { log.error("Error", e); throw e; } finally { try { if (out != null) out.close(); } catch (IOException ex) { } } } private static String getEntryName(File file, String rootPath) { String entryName; String fPath = file.getAbsolutePath(); if (fPath.indexOf(rootPath) != -1) entryName = fPath.substring(rootPath.length() + 1); else entryName = file.getName(); if (file.isDirectory()) entryName += "/";// "/"后缀表示entry是文件夹 return entryName; } }