package com.artfess.base.util; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.commons.CommonsMultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URISyntaxException; import java.net.URL; import java.net.URLEncoder; import java.text.DecimalFormat; import java.util.*; /** * 文件操作工具类 * * @company 广州宏天软件股份有限公司 * @author heyifan * @email heyf@jee-soft.cn * @date 2018年4月11日 */ public class FileUtil { /** * 写入文件 * * @param fileName * 文件名称 * @param content * 文件内容 */ public static void writeFile(String fileName, String content) { writeFile(fileName, content, "utf-8"); } /** * 指定字符集,写入文件。 * * @param fileName * @param content * @param charset */ public static void writeFile(String fileName, String content, String charset) { try(Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), charset));) { createFolder(fileName, true); out.write(content); } catch (IOException e) { e.printStackTrace(); } } /** * 写入文件 * * @param fileName * @param is * @throws IOException */ public static void writeFile(String fileName, InputStream is) throws IOException { try (FileOutputStream fos = new FileOutputStream(fileName);){ byte[] bs = new byte[512]; int n = 0; while ((n = is.read(bs)) != -1) { fos.write(bs, 0, n); } is.close(); } catch (Exception e) {} } /** * 读取文件 * * @param fileName * 文件名称 * @return */ public static String readFile(String fileName) { File file = new File(fileName); String charset = getCharset(file); StringBuffer sb = new StringBuffer(); try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), charset));){ String str = ""; while ((str = in.readLine()) != null) { sb.append(str + "\r\n"); } return sb.toString(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("文件读取失败:"+e.getMessage(),e); } } /** * 读取MultipartFile流中的压缩文件,常用于系统用的导入功能 * @param fileLoad :文件流 * @param fileName :压缩包里面的xml名称 * @return * String * @exception * @since 1.0.0 */ public static String readZip(MultipartFile fileLoad, String fileName) { String xmlStr =""; try { String realFilePath = FileUtil.getWebRootPath() + "/attachFiles/tempZip/"; String name = fileLoad.getOriginalFilename(); String fileDir = name.substring(0, name.lastIndexOf(".")); // 解压文件 ZipUtil.unZipFile(fileLoad, realFilePath); realFilePath = realFilePath + fileDir; xmlStr = FileUtil.readFile(realFilePath + "/" + fileName); FileUtil.deleteDir(new File(realFilePath));// 删除文件 } catch (Exception ex) { } return xmlStr; } /** * 通过类路径读取文件 * * @param filePath * 文件类路径 * @return */ public static String readByClassPath(String filePath) { return readByClassPath(filePath, null); } public static String readByClassPath(String filePath, ClassLoader classLoader) { ClassPathResource classPathResource = new ClassPathResource(filePath); try (InputStream is = classPathResource.getInputStream();InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);){ String s = null; String fileText = ""; while ((s = br.readLine()) != null) { fileText = fileText + s + "\r\n"; } return fileText; } catch (IOException e) { e.printStackTrace(); return null; } } /** * 判断文件是否存在 * * @param dir * @return */ public static boolean isExistFile(String dir) { boolean isExist = false; File fileDir = new File(dir); if (fileDir.isDirectory()) { File[] files = fileDir.listFiles(); if (files != null && files.length != 0) { isExist = true; } } if(fileDir.isFile()){ return fileDir!=null; } return isExist; } /** * 获取文件的字符集 * * @param file * @return */ public static String getCharset(File file) { String charset = "GBK"; byte[] first3Bytes = new byte[3]; try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));){ boolean checked = false; bis.mark(0); int read = bis.read(first3Bytes, 0, 3); if (read == -1){ return charset; } if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) { charset = "UTF-16LE"; checked = true; } else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) { charset = "UTF-16BE"; checked = true; } else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB && first3Bytes[2] == (byte) 0xBF) { charset = "UTF-8"; checked = true; } bis.reset(); if (!checked) { while ((read = bis.read()) != -1) { if (read >= 0xF0) break; // 单独出现BF以下的,也算是GBK if (0x80 <= read && read <= 0xBF) break; if (0xC0 <= read && read <= 0xDF) { read = bis.read(); if (0x80 <= read && read <= 0xBF)// 双字节 (0xC0 - 0xDF) // (0x80 - // 0xBF),也可能在GB编码内 continue; else break; // 也有可能出错,但是几率较小 } else if (0xE0 <= read && read <= 0xEF) { read = bis.read(); if (0x80 <= read && read <= 0xBF) { read = bis.read(); if (0x80 <= read && read <= 0xBF) { charset = "UTF-8"; break; } else break; } else break; } } } } catch (Exception e) { e.printStackTrace(); } return charset; } /** * 读取流到字节数组 * * @param is * @return */ public static byte[] readByte(InputStream is) { try { byte[] r = new byte[is.available()]; is.read(r); return r; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 读取文件到字节数组 * * @param fileName * @return */ public static byte[] readByte(String fileName) { try (FileInputStream fis = new FileInputStream(fileName);){ byte[] r = new byte[fis.available()]; fis.read(r); return r; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 写字节数组到文件 * * @param fileName * @param b * @return */ public static boolean writeByte(String fileName, byte[] b) { try (BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(fileName));){ File file=new File(fileName); if(!file.exists()){ file.createNewFile(); } fos.write(b); return true; } catch (Exception e) { e.printStackTrace(); } return false; } /** * 删除目录 * * @param dir * @return */ public static boolean deleteDir(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (int i = 0; i < children.length; i++) { boolean success = deleteDir(new File(dir, children[i])); if (!success) { return false; } } } return dir.delete(); } /** * 序列化对象到文件 * * @param obj * @param fileName */ public static void serializeToFile(Object obj, String fileName) { try (ObjectOutput out = new ObjectOutputStream(new FileOutputStream(fileName));){ out.writeObject(obj); } catch (IOException e) { e.printStackTrace(); } } /** * 从文件反序列化出对象 * * @param fileName * @return */ public static Object deserializeFromFile(String fileName) { File file = new File(fileName); Object obj = null; try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));){ obj = in.readObject(); } catch (Exception e) {} return obj; } /** * stream 转为字符串 * * @param input * @param charset * @return * @throws IOException */ public static String inputStream2String(InputStream input, String charset) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(input, charset)); StringBuffer buffer = new StringBuffer(); String line = ""; while ((line = in.readLine()) != null) { buffer.append(line + "\n"); } return buffer.toString(); } /** * 将stream按照utf-8编码转换为字符串。 * * @param input * @return * @throws IOException */ public static String inputStream2String(InputStream input) throws IOException { return inputStream2String(input, "utf-8"); } /** * 根据目录取得文件列表 * * @param path * @return */ public static File[] getFiles(String path) { File file = new File(path); return file.listFiles(); } /** * 根据文件路径创建文件夹,如果路径不存在则创建. * * @param path */ public static void createFolderFile(String path) { createFolder(path, true); } /** * 创建文件夹 * * @param path * @param isFile */ public static void createFolder(String path, boolean isFile) { if (isFile) { path = path.substring(0, path.lastIndexOf(File.separator)); } File file = new File(path); if (!file.exists()) file.mkdirs(); } /** * 复制文件来新路径上 * * @param path * 原路径 * @param newPath * 新路径 */ public static void renameFolder(String path, String newName) { File file = new File(path); if (file.exists()) file.renameTo(new File(newName)); } /** * 仅取得文件目录下的子目录。 * * @param dir * 目录 * @return 子目录列表 */ public static ArrayList getDiretoryOnly(File dir) { ArrayList dirs = new ArrayList(); if (dir != null && dir.exists() && dir.isDirectory()) { File[] files = dir.listFiles(new FileFilter() { @Override public boolean accept(File file) { if (file.isDirectory()) return true; return false; } }); for (int i = 0; i < files.length; i++) { dirs.add(files[i]); } } return dirs; } /** * 列出子文件列表 * * @param dir * 指定目录 * @return 子文件列表 */ public ArrayList getFileOnly(File dir) { ArrayList dirs = new ArrayList(); File[] files = dir.listFiles(new FileFilter() { @Override public boolean accept(File file) { if (file.isFile()) return true; return false; } }); for (int i = 0; i < files.length; i++) { dirs.add(files[i]); } return dirs; } /** * 删除文件 * * @param path * @return */ public static boolean deleteFile(String path) { File file = new File(path); return file.delete(); } /** * 文件拷贝 * * @param from * @param to * @return */ public static boolean copyFile(String from, String to) { File fromFile = new File(from); File toFile = new File(to); try (FileInputStream fis = new FileInputStream(fromFile);FileOutputStream fos = new FileOutputStream(toFile);){ int bytesRead; byte[] buf = new byte[4 * 1024]; // 4K buffer while ((bytesRead = fis.read(buf)) != -1) { fos.write(buf, 0, bytesRead); } fos.flush(); } catch (IOException e) { e.printStackTrace(); return false; } return true; } /** * 备份文件。 如果有备份文件,先删除。 * * @param filePath */ public static void backupFile(String filePath) { String backupName = filePath + ".bak"; File file = new File(backupName); if (file.exists()) file.delete(); copyFile(filePath, backupName); } /** * 取得文件扩展名 * * @return */ public static String getFileExt(File file) { if (file.isFile()) { return getFileExt(file.getName()); } return ""; } /** * 根据文件名获取扩展名称。 * * @param fileName * @return */ public static String getFileExt(String fileName) { int pos = fileName.lastIndexOf("."); if (pos > -1) { return fileName.substring(pos + 1).toLowerCase(); } return ""; } /** * copy目录 * * @param fromDir * 源目录 * @param toDir * 目标目录 * @throws IOException */ public static void copyDir(String fromDir, String toDir) throws IOException { (new File(toDir)).mkdirs(); File[] file = (new File(fromDir)).listFiles(); for (int i = 0; i < file.length; i++) { if (file[i].isFile()) { String fromFile = file[i].getAbsolutePath(); String toFile = toDir + "/" + file[i].getName(); copyFile(fromFile, toFile); } if (file[i].isDirectory()) copyDirectiory(fromDir + "/" + file[i].getName(), toDir + "/" + file[i].getName()); } } /** * 递规调用目录拷贝。 * * @param fromDir * 源目录 * @param toDir * 目标目录 * @throws IOException */ private static void copyDirectiory(String fromDir, String toDir) throws IOException { (new File(toDir)).mkdirs(); File[] file = (new File(fromDir)).listFiles(); for (int i = 0; i < file.length; i++) { if (file[i].isFile()) { String fromName = file[i].getAbsolutePath(); String toFile = toDir + "/" + file[i].getName(); copyFile(fromName, toFile); } if (file[i].isDirectory()) copyDirectiory(fromDir + "/" + file[i].getName(), toDir + "/" + file[i].getName()); } } /** * 取得文件大小 * * @return 返回文件大小 * @throws IOException */ public static String getFileSize(File file) throws IOException { if (file.isFile()) { int size = 0; try (FileInputStream fis = new FileInputStream(file);){ size = fis.available(); } catch (Exception e) { e.printStackTrace(); } return getSize((double) size); } return ""; } /** * 根据字节大小获取带单位的大小。 * * @param size * @return */ public static String getSize(double size) { DecimalFormat df = new DecimalFormat("0.00"); if (size > 1024 * 1024) { double ss = size / (1024 * 1024); return df.format(ss) + " M"; } else if (size > 1024) { double ss = size / 1024; return df.format(ss) + " KB"; } else { return size + " bytes"; } } /** * 取得文件的相对父目录 * * @param baseDir * 基准目录 * @param currentFile * 当前文件 * @return 相对基准目录路径 */ public static String getParentDir(String baseDir, String currentFile) { File f = new File(currentFile); String parentPath = f.getParent(); String path = parentPath.replace(baseDir, ""); return path.replace(File.separator, "/"); } /** * 根据键在属性文件中获取数据。 * * @param fileName * 属性文件名称。 * @param key * 属性的键值。 * @return */ public static String readFromProperties(String fileName, String key) { String value = ""; InputStream stream = null; try { stream = new BufferedInputStream(new FileInputStream(fileName)); Properties prop = new Properties(); prop.load(stream); value = prop.getProperty(key); } catch (Exception e) { e.printStackTrace(); } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } } return value; } /** * 保存属性文件。 * * @param fileName * 文件名 * @param key * 键名 * @param value * 键值 * @return 保存是否成功。 */ public static boolean saveProperties(String fileName, String key, String value) { StringBuffer sb = new StringBuffer(); boolean isFound = false; BufferedReader in = null; try { in = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), "utf-8")); String str; while ((str = in.readLine()) != null) { if (str.startsWith(key)) { sb.append(key + "=" + value + "\r\n"); isFound = true; } else { sb.append(str + "\r\n"); } } // 添加新的键值。 if (!isFound) { sb.append(key + "=" + value + "\r\n"); } FileUtil.writeFile(fileName, sb.toString(), "utf-8"); return true; } catch (Exception ex) { ex.printStackTrace(); return false; } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 删除属性key。 * * @param fileName * @param key * @return */ public static boolean delProperties(String fileName, String key) { StringBuffer sb = new StringBuffer(); BufferedReader in = null; try { in = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), "utf-8")); String str; while ((str = in.readLine()) != null) { if (!str.startsWith(key)) { sb.append(str + "\r\n"); } } FileUtil.writeFile(fileName, sb.toString(), "utf-8"); return true; } catch (Exception ex) { ex.printStackTrace(); return false; } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 获取接口的所有实现类 * * @param interfaceClass * 接口类 * @param samePackage * 是否为同一包路径下 * @return * @throws ClassNotFoundException * @throws IOException */ public static List> getAllClassesByInterface(Class interfaceClass, boolean samePackage) throws IOException, ClassNotFoundException, IllegalStateException { if (!interfaceClass.isInterface()) { throw new IllegalStateException("Class not a interface."); } ClassLoader $loader = interfaceClass.getClassLoader(); /** 获取包名称 */ String packageName = samePackage ? interfaceClass.getPackage().getName() : "/"; return findClasses(interfaceClass, $loader, packageName); } /** * 获取实现接口的实现类文件 * * @param interfaceClass * @param loader * @param packageName * @return * @throws IOException * @throws ClassNotFoundException */ private static List> findClasses(Class interfaceClass, ClassLoader loader, String packageName) throws IOException, ClassNotFoundException { List> allClasses = new ArrayList>(); /** 获取包路径 */ String packagePath = packageName.replace(".", "/"); if (!packagePath.equals("/")) { Enumeration resources = loader.getResources(packagePath); while (resources.hasMoreElements()) { URL $url = resources.nextElement(); allClasses.addAll(findResources(interfaceClass, new File($url.getFile()), packageName)); } } else { String path = loader.getResource("").getPath(); allClasses.addAll(findResources(interfaceClass, new File(path), packageName)); } return allClasses; } /** * 获取文件资源信息 * * @param interfaceClass * @param directory * @param packageName * @return * @throws ClassNotFoundException */ @SuppressWarnings("unchecked") private static List> findResources(Class interfaceClass, File directory, String packageName) throws ClassNotFoundException { List> $results = new ArrayList>(); if (!directory.exists()) return Collections.EMPTY_LIST; File[] files = directory.listFiles(); for (File file : files) { if (file.isDirectory()) { // 文件夹-->继续遍历 if (!file.getName().contains(".")) { if (!packageName.equals("/")) { $results.addAll(findResources(interfaceClass, file, packageName + "." + file.getName())); } else { $results.addAll(findResources(interfaceClass, file, file.getName())); } } } else if (file.getName().endsWith(".class")) { Class clazz = null; if (!packageName.equals("/")) { clazz = Class.forName(packageName + "." + file.getName().substring(0, file.getName().length() - 6)); } else { clazz = Class.forName(file.getName().substring(0, file.getName().length() - 6)); } if (interfaceClass.isAssignableFrom(clazz) && !interfaceClass.equals(clazz)) { $results.add(clazz); } } } return $results; } /** * 深度克隆对象。 * *
	 * 	将一个对象序列化一个内存数据组。
	 *  在从数组中反序列化这个类。
	 * 
* * @param obj * @return * @throws Exception */ public static Object cloneObject(Object obj) throws Exception { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(obj); out.close(); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream in = new ObjectInputStream(byteIn); Object rtn = in.readObject(); in.close(); return rtn; } /** * 获取classes路径。 * * @return * 返回如下的路径E:/work/x5/x5-base-root/modules/x5-base-core/target/classes * 。 * @throws URISyntaxException */ public static String getClassesPath() { String path = FileUtil.class.getClassLoader().getResource("").getPath(); if ("\\".equals(File.separator)) { path = StringUtil.trimPrefix(path, "/"); } path = path.replace("\\", "/"); path = StringUtil.trimSuffix(path, "/"); return path; } public static void main(String[] args) { System.out.println(FileUtil.getClassesPath()); } /** * 获取应用程序根路径。 * * @return 返回如下路径 E:/work/bpm/src/main/webapp * @throws Exception */ public static String getWebRootPath() { String path = getClassesPath(); path = path.substring(0, path.lastIndexOf("WEB-INF")); path = StringUtil.trimSuffix(path, "/"); return path; } /** * 将输入流写入到输出流中。 * @param is * @param out * @throws IOException */ public static void writeInput(InputStream is, OutputStream out) throws IOException{ try { byte[] bs = new byte[1024]; int n = 0; while ((n = is.read(bs)) != -1) { out.write(bs, 0, n); } out.flush(); } catch (Exception ex) { ex.printStackTrace(); } finally { if (is != null) is.close(); if (out != null) out.close(); } } /** * 获取临时文件输出的临时目录 * @return */ public static String getIoTmpdir(){ return System.getProperty("java.io.tmpdir"); } /** * 将文件流转化为MultipartFile对象 * @param file * @return */ public static MultipartFile fileToMultipartFile(File file) { FileItem fileItem = createFileItem(file); MultipartFile multipartFile = new CommonsMultipartFile(fileItem); return multipartFile; } private static FileItem createFileItem(File file) { FileItemFactory factory = new DiskFileItemFactory(16, null); FileItem item = factory.createItem("textField", "text/plain", true, file.getName()); int bytesRead = 0; byte[] buffer = new byte[8192]; try { FileInputStream fis = new FileInputStream(file); OutputStream os = item.getOutputStream(); while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); fis.close(); } catch (IOException e) { e.printStackTrace(); } return item; } public static void fileDownload(final HttpServletResponse response, InputStream inputStream, String fileName) throws Exception { byte[] data = org.aspectj.util.FileUtil.readAsByteArray(inputStream); fileDownload(response, data, fileName); } /** * @param response * @param fileName //下载后看到的文件名 * @return 文件名 */ public static void fileDownload(final HttpServletResponse response, byte[] data, String fileName) throws Exception { fileName = URLEncoder.encode(fileName, "UTF-8"); response.reset(); response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); response.addHeader("Content-Length", "" + data.length); response.setContentType("application/octet-stream;charset=UTF-8"); response.setHeader("Access-Control-Allow-Origin", "*"); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); outputStream.write(data); outputStream.flush(); outputStream.close(); response.flushBuffer(); } }