|
@@ -0,0 +1,422 @@
|
|
|
+/*
|
|
|
+ * *************************************************
|
|
|
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
|
|
|
+ * Created by Deason on 2018-07-12 15:31:10.
|
|
|
+ * *************************************************
|
|
|
+ */
|
|
|
+
|
|
|
+package cn.com.qmth.examcloud.core.questions.base.converter.utils;
|
|
|
+
|
|
|
+import org.apache.commons.io.IOUtils;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import java.io.*;
|
|
|
+import java.nio.charset.Charset;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.*;
|
|
|
+import java.util.zip.ZipEntry;
|
|
|
+import java.util.zip.ZipFile;
|
|
|
+import java.util.zip.ZipOutputStream;
|
|
|
+
|
|
|
+public class FileUtil {
|
|
|
+ private static Logger log = LoggerFactory.getLogger(FileUtil.class);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分隔文件
|
|
|
+ *
|
|
|
+ * @param sourcePath 原文件
|
|
|
+ * @param targetPath 目标文件
|
|
|
+ * @param n 跳过的字节数
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static File cutFile(String sourcePath, String targetPath, int n) {
|
|
|
+ FileInputStream fis = null;
|
|
|
+ InputStream is = null;
|
|
|
+ OutputStream os = null;
|
|
|
+ try {
|
|
|
+ File file = new File(sourcePath);
|
|
|
+ fis = new FileInputStream(file);
|
|
|
+ //从n个字节开始读,注意中文是两个字节
|
|
|
+ fis.skip(n);
|
|
|
+ //指定文件位置读取的文件流
|
|
|
+ is = new BufferedInputStream(fis);
|
|
|
+ //存入新文件
|
|
|
+ File newFile = new File(targetPath);
|
|
|
+ os = new FileOutputStream(newFile);
|
|
|
+ byte buffer[] = new byte[4 * 1024];
|
|
|
+ int len;
|
|
|
+ while ((len = is.read(buffer)) != -1) {
|
|
|
+ os.write(buffer, 0, len);
|
|
|
+ }
|
|
|
+ os.flush();
|
|
|
+ return newFile;
|
|
|
+ } catch (FileNotFoundException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ } finally {
|
|
|
+ IOUtils.closeQuietly(fis);
|
|
|
+ IOUtils.closeQuietly(is);
|
|
|
+ IOUtils.closeQuietly(os);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 读取文件前面部分N个字节
|
|
|
+ *
|
|
|
+ * @param path 文件路径
|
|
|
+ * @param headerSize 头信息字节数(必须2的倍数)
|
|
|
+ * @param signSize 签名信息字节数
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String[] readFileHeader(String path, int headerSize, int signSize) {
|
|
|
+ int n = headerSize / 2;
|
|
|
+ String[] codes = new String[n + 1];
|
|
|
+ FileInputStream fis = null;
|
|
|
+ DataInputStream ois = null;
|
|
|
+ try {
|
|
|
+ File file = new File(path);
|
|
|
+ fis = new FileInputStream(file);
|
|
|
+ ois = new DataInputStream(fis);
|
|
|
+ //分n次读取文件(n * 2)个字节
|
|
|
+ for (int i = 0; i < n; i++) {
|
|
|
+ codes[i] = String.valueOf(ois.readShort());
|
|
|
+ }
|
|
|
+ if (signSize > 0) {
|
|
|
+ StringBuilder ss = new StringBuilder();
|
|
|
+ for (int i = 0; i < signSize; i++) {
|
|
|
+ ss.append((char) ois.readByte());
|
|
|
+ }
|
|
|
+ codes[2] = ss.toString();
|
|
|
+ }
|
|
|
+ } catch (FileNotFoundException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ } finally {
|
|
|
+ IOUtils.closeQuietly(fis);
|
|
|
+ IOUtils.closeQuietly(ois);
|
|
|
+ }
|
|
|
+ return codes;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 读取文件内容
|
|
|
+ *
|
|
|
+ * @param file
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String readFileContent(File file) {
|
|
|
+ StringBuilder content = new StringBuilder();
|
|
|
+ InputStreamReader streamReader = null;
|
|
|
+ BufferedReader bufferedReader = null;
|
|
|
+ try {
|
|
|
+ String encoding = "UTF-8";
|
|
|
+ if (file.exists() && file.isFile()) {
|
|
|
+ streamReader = new InputStreamReader(new FileInputStream(file), encoding);
|
|
|
+ bufferedReader = new BufferedReader(streamReader);
|
|
|
+ String line;
|
|
|
+ while ((line = bufferedReader.readLine()) != null) {
|
|
|
+ content.append(line);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ } finally {
|
|
|
+ IOUtils.closeQuietly(streamReader);
|
|
|
+ IOUtils.closeQuietly(bufferedReader);
|
|
|
+ }
|
|
|
+ return content.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 在文件流前面追加头信息和签名信息,并生成新的“.tk”文件
|
|
|
+ */
|
|
|
+ public static boolean appendHeader(File file, short[] headers, String sign) {
|
|
|
+ FileInputStream fis = null;
|
|
|
+ InputStream is = null;
|
|
|
+ FileOutputStream fos = null;
|
|
|
+ DataOutputStream dos = null;
|
|
|
+ if (file == null || !file.exists()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!file.isFile()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ //创建临时文件
|
|
|
+ String baseFilePath = file.getAbsolutePath();
|
|
|
+ String targetFilePath = getFilePathName(baseFilePath) + ".tk";
|
|
|
+ File newFile = new File(targetFilePath);
|
|
|
+ fos = new FileOutputStream(newFile);
|
|
|
+ dos = new DataOutputStream(fos);
|
|
|
+ //写入头信息
|
|
|
+ for (short s : headers) {
|
|
|
+ dos.writeShort(s);
|
|
|
+ }
|
|
|
+ if (sign != null && !"".equals(sign)) {
|
|
|
+ //写入签名信息
|
|
|
+ dos.write(sign.getBytes("ISO-8859-1"));
|
|
|
+ }
|
|
|
+ //在临时文件中追加原始文件内容
|
|
|
+ fis = new FileInputStream(file);
|
|
|
+ is = new BufferedInputStream(fis);
|
|
|
+ byte buffer[] = new byte[4 * 1024];
|
|
|
+ int len;
|
|
|
+ while ((len = is.read(buffer)) != -1) {
|
|
|
+ dos.write(buffer, 0, len);
|
|
|
+ }
|
|
|
+ dos.flush();
|
|
|
+ return true;
|
|
|
+ } catch (FileNotFoundException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ } finally {
|
|
|
+ IOUtils.closeQuietly(is);
|
|
|
+ IOUtils.closeQuietly(fis);
|
|
|
+ IOUtils.closeQuietly(dos);
|
|
|
+ IOUtils.closeQuietly(fos);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成日期目录路径
|
|
|
+ */
|
|
|
+ public static String generateDateDir() {
|
|
|
+ return "/" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "/";
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String generateFileName() {
|
|
|
+ return UUID.randomUUID().toString().replaceAll("-", "");
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String generateDateName() {
|
|
|
+ return new SimpleDateFormat("yyMMddHHmmss").format(new Date());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取文件后缀名(包含".")
|
|
|
+ */
|
|
|
+ public static String getFileSuffix(String fileName) {
|
|
|
+ if (fileName == null) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ int index = fileName.lastIndexOf(".");
|
|
|
+ if (index > -1) {
|
|
|
+ return fileName.substring(index).toLowerCase();
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取无后缀的文件名
|
|
|
+ *
|
|
|
+ * @param fileName 示例:../xxx/abc.xx
|
|
|
+ * @return 示例:../xxx/abc
|
|
|
+ */
|
|
|
+ public static String getFilePathName(String fileName) {
|
|
|
+ if (fileName != null && fileName.length() > 0) {
|
|
|
+ int index = fileName.lastIndexOf(".");
|
|
|
+ if (index != -1) {
|
|
|
+ return fileName.substring(0, index);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建文件目录
|
|
|
+ */
|
|
|
+ public static boolean makeDirs(String path) {
|
|
|
+ if (path == null || "".equals(path)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ File folder = new File(path);
|
|
|
+ if (!folder.exists()) {
|
|
|
+ return folder.mkdirs();
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存字符串到文件中
|
|
|
+ */
|
|
|
+ public static void saveAsFile(String path, String content) {
|
|
|
+ saveAsFile(path, content, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void saveAsFile(String path, String content, String encoding) {
|
|
|
+ if (path == null || content == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (encoding == null) {
|
|
|
+ encoding = "UTF-8";
|
|
|
+ }
|
|
|
+ BufferedWriter bw = null;
|
|
|
+ try {
|
|
|
+ File file = new File(path);
|
|
|
+ if (!file.exists()) {
|
|
|
+ if (FileUtil.makeDirs(file.getParent())) {
|
|
|
+ file.createNewFile();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(file), encoding);
|
|
|
+ bw = new BufferedWriter(write);
|
|
|
+ bw.write(content);
|
|
|
+ log.info("save as file success. " + path);
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("save as file error. " + path);
|
|
|
+ } finally {
|
|
|
+ try {
|
|
|
+ if (bw != null) {
|
|
|
+ bw.flush();
|
|
|
+ bw.close();
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解压文件
|
|
|
+ *
|
|
|
+ * @param targetDir 解压目录
|
|
|
+ * @param zipFile 待解压的ZIP文件
|
|
|
+ */
|
|
|
+ public static List<File> unZip(File targetDir, File zipFile) throws IOException {
|
|
|
+ if (targetDir == null) {
|
|
|
+ log.error("解压目录不能为空!");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (zipFile == null) {
|
|
|
+ log.error("待解压的文件不能为空!");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (!zipFile.exists()) {
|
|
|
+ log.error("待解压的文件不存在!" + zipFile.getAbsolutePath());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String zipName = zipFile.getName().toLowerCase();
|
|
|
+ if (zipFile.isDirectory() || zipName.indexOf(".zip") < 0) {
|
|
|
+ log.error("待解压的文件格式错误!");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (!targetDir.exists()) {
|
|
|
+ targetDir.mkdir();
|
|
|
+ }
|
|
|
+ log.info("UnZip targetDir:" + targetDir.getAbsolutePath());
|
|
|
+ List<File> result = new LinkedList<>();
|
|
|
+ ZipFile zip = new ZipFile(zipFile, Charset.forName("UTF-8"));
|
|
|
+ Enumeration entries = zip.entries();
|
|
|
+ while (entries.hasMoreElements()) {
|
|
|
+ ZipEntry entry = (ZipEntry) entries.nextElement();
|
|
|
+ //Linux中需要替换掉路径的反斜杠
|
|
|
+ String entryName = (File.separator + entry.getName()).replaceAll("\\\\", "/");
|
|
|
+ log.info("UnZip:" + entryName);
|
|
|
+ String filePath = targetDir.getAbsolutePath() + entryName;
|
|
|
+ File target = new File(filePath);
|
|
|
+ if (entry.isDirectory()) {
|
|
|
+ target.mkdirs();
|
|
|
+ } else {
|
|
|
+ File dir = target.getParentFile();
|
|
|
+ if (!dir.exists()) {
|
|
|
+ dir.mkdirs();
|
|
|
+ }
|
|
|
+ OutputStream os = new FileOutputStream(target);
|
|
|
+ InputStream is = zip.getInputStream(entry);
|
|
|
+ IOUtils.copy(is, os);
|
|
|
+ os.flush();
|
|
|
+ IOUtils.closeQuietly(os);
|
|
|
+ IOUtils.closeQuietly(is);
|
|
|
+ result.add(target);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ zip.close();
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 文件压缩
|
|
|
+ *
|
|
|
+ * @param target 目录或文件
|
|
|
+ * @param zipFile 压缩后的ZIP文件
|
|
|
+ */
|
|
|
+ public static boolean doZip(File target, File zipFile) {
|
|
|
+ if (target == null || !target.exists()) {
|
|
|
+ log.error("目录或文件不能为空!");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (zipFile == null) {
|
|
|
+ log.error("待压缩的文件不能为空!");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ ZipOutputStream zipOutStream = null;
|
|
|
+ OutputStream outStream = null;
|
|
|
+ try {
|
|
|
+ if (!zipFile.exists()) {
|
|
|
+ zipFile.createNewFile();
|
|
|
+ }
|
|
|
+ outStream = new FileOutputStream(zipFile);
|
|
|
+ zipOutStream = new ZipOutputStream(outStream, Charset.forName("UTF-8"));
|
|
|
+ if (target.isDirectory()) {
|
|
|
+ File[] files = target.listFiles();
|
|
|
+ if (files.length == 0) {
|
|
|
+ log.error("文件夹内未找到任何文件!");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ for (File file : files) {
|
|
|
+ doZip(zipOutStream, file, null);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ doZip(zipOutStream, target, null);
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ } finally {
|
|
|
+ if (zipOutStream != null) {
|
|
|
+ IOUtils.closeQuietly(zipOutStream);
|
|
|
+ }
|
|
|
+ if (outStream != null) {
|
|
|
+ IOUtils.closeQuietly(outStream);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void doZip(ZipOutputStream zipOutStream, File target, String parentDir) throws IOException {
|
|
|
+ //log.info("Zip:" + parentDir);
|
|
|
+ if (parentDir == null) {
|
|
|
+ parentDir = "";
|
|
|
+ }
|
|
|
+ if (!"".equals(parentDir) && !parentDir.endsWith(File.separator)) {
|
|
|
+ parentDir += File.separator;
|
|
|
+ }
|
|
|
+ if (target.isDirectory()) {
|
|
|
+ File[] files = target.listFiles();
|
|
|
+ if (files.length > 0) {
|
|
|
+ for (File file : files) {
|
|
|
+ doZip(zipOutStream, file, parentDir + target.getName());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ zipOutStream.putNextEntry(new ZipEntry(parentDir + target.getName()));
|
|
|
+ zipOutStream.closeEntry();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ InputStream is = new FileInputStream(target);
|
|
|
+ zipOutStream.putNextEntry(new ZipEntry(parentDir + target.getName()));
|
|
|
+ int len = 0;
|
|
|
+ byte[] bytes = new byte[1024];
|
|
|
+ while ((len = is.read(bytes)) > 0) {
|
|
|
+ zipOutStream.write(bytes, 0, len);
|
|
|
+ }
|
|
|
+ IOUtils.closeQuietly(is);
|
|
|
+ zipOutStream.closeEntry();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|