Android日志输出到控制台、文件(XLog开源日志工具)

您所在的位置:网站首页 文件类型xlog Android日志输出到控制台、文件(XLog开源日志工具)

Android日志输出到控制台、文件(XLog开源日志工具)

2024-01-06 04:23| 来源: 网络整理| 查看: 265

Android日志输出到控制台、文件(XLog开源日志工具)

Android项目开发中,需要将Log同时输出到控制台 与 文件,并要求将日志文件压缩并上传到远程服务端(便于分析App使用过程中用户反馈的Bug,进行问题定位与修复):

打印到控制台: 软件研发阶段,方便Debug调试;打印到文件: 软件上线后,方便线上问题的跟踪分析;日志文件压缩上传: 用户反馈遇到的Bug后,以此文件分析用户用户的操作行为,从而修复Bug。

本文介绍的一个开源日志工具为XLog。 XLog具备如下两种模式:

Debug模式: 日志输出到控制台,同时输出到App内置存储路径下的文件中;Release模式: 日志输出到App内置存储路径下的文件中,同时禁止控制台日志打印;

Debug模式 / Release模式均支持如下功能:

日志压缩上传: 支持日志压缩上传,便于对用户反馈的Bug进行定位分析。日志关键词筛选: 支持通过日志关键词进行筛选,默认为XLogCore。Exception错误信息打印: 支持Exception错误信息打印。 一、效果举例 1.1 日志 输出到 控制台

日志输出到控制台,同时支持日志筛选关键词、打印Excetption日志。 在这里插入图片描述

1.2 日志 输出到 文件

日志默认输出到,同时支持日志筛选关键词、打印Excetption日志。

日志文件在 未进行压缩时,存储于App内部存储 /data/data/包名/files/xlog 路径下。 在这里插入图片描述

日志文件 进行压缩后,存储到Sdcard存储 /sdcard/Android/data/包名/file/zip_log 路径下。 在这里插入图片描述

写入日志文件的数据如下: 请添加图片描述

二、使用方式 XLog 初始化XLog 打印日志XLog 文件压缩上传 2.1、XLog 初始化

Application的onCreate方法中进行XLog初始化; Application的onTrimMemory方法中进行文件IO流的关闭。

public class MainApplication extends Application { @Override public void onCreate() { super.onCreate(); // Application的onCreate方法中进行XLog初始化 // 初始化日志(debug模式 日志输出到) XLog.onAppCreate(MainApplication.this, true); } @Override public void onTrimMemory(int level) { super.onTrimMemory(level); // Application的onTrimMemory方法中进行文件IO流的关闭 // 程序在内存清理的时候执行 XLog.onAppTrimMemory(); } } 2.2、XLog 打印日志 // 打印到控制台;同时打印到文件; XLog.d(TAG, "---onCreate---"); // 打印 Exception 信息 try { int tt = 5 / 0; } catch (Exception e) { XLog.d(TAG, "XLog Exception", e); } 2.3、XLog 文件压缩上传 // 文件压缩,并返回压缩后的文件路径 String filePath = XLog.zipLogFiles(); // toast 文件路径 if (!TextUtils.isEmpty(filePath)) { Toast.makeText(MainActivity.this, "日志文件生成成功:" + filePath, Toast.LENGTH_LONG).show(); } 三、源码

Github源码地址: https://github.com/xiaxveliang/Android_XLoger

XLog.java

/** * create by xiaxl on 2019.12.05 *

* 日志 */ public class XLog { // private static XLogCore mLog = XLogCore.getInstance(); // application进入 onCreate 时调用 public static void onAppCreate(Context context, boolean isDebug) { mLog.onAppCreate(context, isDebug ? XLogCore.XLogModel.MODEL_DEBUG : XLogCore.XLogModel.MODEL_RELEASE); } // application进入 onLowMemory 时调用 public static void onAppTrimMemory() { mLog.onAppTrimMemory(); } // 日志文件在 未进行压缩时 ,存储于App内部存储 /data/data/包名/files/xlog 路径下。 // 日志文件 进行压缩后 ,存储到Sdcard存储 /sdcard/Android/data/包名/file/zip_log 路径下。 public static String zipLogFiles() { return mLog.zipLogFiles(); } // 打印日志 public static void v(String tag, String msg) { mLog.v(tag, msg); } public static void v(String tag, String msg, Throwable throwable) { mLog.v(tag, msg, throwable); } public static void d(String tag, String msg) { mLog.d(tag, msg); } public static void d(String tag, String msg, Throwable throwable) { mLog.d(tag, msg, throwable); } public static void i(String tag, String msg) { mLog.i(tag, msg); } public static void i(String tag, String msg, Throwable throwable) { mLog.i(tag, msg, throwable); } public static void w(String tag, String msg) { mLog.w(tag, msg); } public static void w(String tag, String msg, Throwable throwable) { mLog.w(tag, msg, throwable); } public static void e(String tag, String msg) { mLog.e(tag, msg); } public static void e(String tag, String msg, Throwable throwable) { mLog.e(tag, msg, throwable); } }

XLoger.java

/** * 日志工具 * 1、debug 为 true 时,展示在控制台;同时缓存到内部缓存的xlog文件中; * 2、debug 为 fase 时,只缓存到内部缓存的xlog文件中; *

* Log文件缓存目录: * /data/data/%packetname%/files/ */ public class XLogCore { /** * 配置信息 */ private static class XLogConfig { /** * App可通过该tag 查看筛选日志信息 */ private static final String XLOG_TAG = "XLogCore"; /** * 日志文件的构成:xlog_20201111_111111.txt */ // 日志缓存文件夹 private static final String XLOG_FILE_DIR = "xlog"; // 日志归档文件夹(日志超过一定大小后,归档到该路径) private static final String XLOG_FILING_DIR = "filing"; // 日志文件的最大长度(字节Byte) 15M private static final int XLOG_FILE_MAXSIZE = 30 * 1024 * 1024; // 默认 pre name private static final String XLOG_FILE_NAME_PRE = "xlog_"; // 日志文件扩展名 private static final String XLOG_FILE_NAME_FORMAT = ".txt"; /** * 输出控制 */ // 输出到控制台 or 输出到文件 private static final int SHOW_LOG_CONSOLE = 0x01; // 输出到控制台 private static final int SHOW_LOG_FILE = 0x10; // 输出到文件 /** * 单线程池(用于异步写文件) */ private static ExecutorService mExecutorService = Executors.newFixedThreadPool(1); /** * 日志压缩后的文件夹名称 */ // 压缩后的缓存文件 文件夹名称 private static final String XLOG_ZIP_DIR = "xlog_zip"; } // 注解仅存在于源码中,在class字节码文件中不包含 @Retention(RetentionPolicy.SOURCE) // 限定取值范围为{MODEL_DEBUG, MODEL_RELEASE} @IntDef({XLogModel.MODEL_DEBUG, XLogModel.MODEL_RELEASE}) public @interface XLogModel { // debug模式:打印到控制台 和 文件 int MODEL_DEBUG = XLogConfig.SHOW_LOG_CONSOLE | XLogConfig.SHOW_LOG_FILE; // release模式:打印到文件 int MODEL_RELEASE = XLogConfig.SHOW_LOG_FILE; } /** * 当前文件信息记录 */ public static class XLogInfoBean { // 文件名 xlog_yyyyMMdd_HHmmss.txt public String xLogName = ""; // 文件大小(字节大小) public long xLogSize = 0; } // ############################################################################# /** * 内部变量 */ private Context mContext; // 文件读写锁 private Object mLockObj = new Object(); // 日志打印级别 private final int mLogPrintLevel = Log.VERBOSE; // // 日志缓存路径(内部缓存):/data/data/%packetname%/files/xlog private String mLogFileDir; // 日志文件归档路径 private String mLogFilingDir; /** * 用户变量 */ // debug 开关 (默认为debug模式) @XLogCore.XLogModel private int mDebugModel = XLogModel.MODEL_DEBUG; // 当前文件信息记录 private XLogInfoBean mCurrLogFileInfo = null; // 文件IO private OutputStream mCurrLogFileStream = null; /** * 单例 */ private static volatile XLogCore instance; private XLogCore() { } public static XLogCore getInstance() { if (instance == null) { synchronized (XLogCore.class) { if (instance == null) { instance = new XLogCore(); } } } return instance; } // ############################################################################# /** * application进入 onCreate 时调用 * * @param context application的context * @param debugModel debug or release */ public void onAppCreate(Context context, @XLogCore.XLogModel int debugModel) { if (context == null) { Log.e("XLoger", "context need init"); return; } this.mContext = context; this.mDebugModel = debugModel; /** * 读取data/data下缓存日志文件 */ loadLogFileInfo(); } /** * application进入 onTrimMemory 时调用 */ public void onAppTrimMemory() { closeFileStream(); } /** * 压缩日志文件 返回压缩后的文件存储路径 *

* 建议:异步任务中执行 *

* 日志文件在 未进行压缩时 ,存储于App内部存储 /data/data/包名/files/xlog 路径下。 * 日志文件 进行压缩后 ,存储到Sdcard存储 /sdcard/Android/data/包名/file/zip_log 路径下。 * * @return */ public String zipLogFiles() { if (mContext == null) { Log.e("XLoger", "context need init"); return ""; } if (TextUtils.isEmpty(mLogFileDir)) { Log.e("XLoger", "mLogFileDir isEmpty"); return ""; } String logFileDir = mLogFileDir; // if (!TextUtils.isEmpty(logFileDir)) { // 当前时间作为 zip文件 的文件名称 final String desZipFilePath = XLogStoreUtil.genDesZipFilePath(mContext); File desZipFile = new File(desZipFilePath); // 内部缓存路径下 log 文件的缓存路径 List srcFilePaths = new ArrayList(); srcFilePaths.add(logFileDir); // 压缩文件 boolean flag = ZipFileUtil.exportZipFromPaths(srcFilePaths, desZipFile); // 压缩成功,则返回对应的文件存储路径 if (flag) { return desZipFilePath; } } return ""; } // ############################################################################# public void v(String tagFromUser, String msgFromUser) { XLogCore.this.v(tagFromUser, msgFromUser, null); } public void v(String tagFromUser, String msgFromUser, Throwable throwable) { showLog(tagFromUser, msgFromUser, throwable, mDebugModel, Log.VERBOSE); } public void d(String tagFromUser, String msgFromUser) { XLogCore.this.d(tagFromUser, msgFromUser, null); } public void d(String tagFromUser, String msgFromUser, Throwable throwable) { showLog(tagFromUser, msgFromUser, throwable, mDebugModel, Log.DEBUG); } public void i(String tagFromUser, String msgFromUser) { XLogCore.this.i(tagFromUser, msgFromUser, null); } public void i(String tagFromUser, String msgFromUser, Throwable throwable) { showLog(tagFromUser, msgFromUser, throwable, mDebugModel, Log.INFO); } public void w(String tagFromUser, String msgFromUser) { XLogCore.this.w(tagFromUser, msgFromUser, null); } public void w(String tagFromUser, String msgFromUser, Throwable throwable) { showLog(tagFromUser, msgFromUser, throwable, mDebugModel, Log.WARN); } public void e(String tagFromUser, String msgFromUser) { XLogCore.this.e(tagFromUser, msgFromUser, null); } public void e(String tagFromUser, String msgFromUser, Throwable throwable) { showLog(tagFromUser, msgFromUser, throwable, mDebugModel, Log.ERROR); } // ############################################################################# /** * 打印到文件 或 打印到控制台 * * @param tagFromUser * @param msgFromUser * @param xLogModel @XLoger.XLogModel * @param logPrintLevel log打印级别 */ private void showLog(String tagFromUser, String msgFromUser, Throwable throwable, @XLogCore.XLogModel int xLogModel, int logPrintLevel) { if (mContext == null) { Log.e("XLoger", "context need init"); return; } if (TextUtils.isEmpty(mLogFileDir)) { Log.e("XLoger", "mLogFileDir isEmpty"); return; } if (TextUtils.isEmpty(tagFromUser)) { tagFromUser = "USER_TAG_NULL"; } if (TextUtils.isEmpty(msgFromUser)) { msgFromUser = "USER_MSG_NULL"; } if (logPrintLevel logToConsole(tagFromUser, msgFromUser, throwable, logPrintLevel); } // 输出到文件 if ((xLogModel & XLogConfig.SHOW_LOG_FILE) != 0) { // final String tagFromUser2File = tagFromUser; final String msgFromUser2File = msgFromUser; final Throwable throwable2File = throwable; try { if (XLogConfig.mExecutorService != null) { XLogConfig.mExecutorService.submit(new Runnable() { public void run() { XLogCore.this.logToFile(tagFromUser2File, msgFromUser2File, throwable2File); } }); } } catch (Exception e) { e.printStackTrace(); } } } // ############################################################################# /** * 将log打到控制台 * * @param tagFromUser * @param msgFromUser * @param level */ private void logToConsole(String tagFromUser, String msgFromUser, Throwable throwable, int level) { // 日志打印 String logTag = XLogConfig.XLOG_TAG; String logMsg = getConsoleLogMsg(tagFromUser, msgFromUser, throwable); switch (level) { case Log.DEBUG: Log.d(logTag, logMsg); break; case Log.ERROR: Log.e(logTag, logMsg); break; case Log.INFO: Log.i(logTag, logMsg); break; case Log.VERBOSE: Log.v(logTag, logMsg); break; case Log.WARN: Log.w(logTag, logMsg); break; } } /** * 组合用户 tagFromUser + msgFromUser + Exception * * @param msgFromUser * @return */ private String getConsoleLogMsg(String tagFromUser, String msgFromUser, Throwable throwable) { StringBuffer sb = new StringBuffer(); sb.append(tagFromUser); sb.append(": "); sb.append(msgFromUser); if (throwable != null) { sb.append("\n"); sb.append(Log.getStackTraceString(throwable)); } return sb.toString(); } // ############################################################################# /** * 读取data/data下缓存日志文件信息 */ private void loadLogFileInfo() { // 路径空 if (mContext == null) { Log.e("XLoger", "context need init"); return; } // 异步读取文件信息 try { if (XLogConfig.mExecutorService != null) { XLogConfig.mExecutorService.submit(new Runnable() { public void run() { synchronized (mLockObj) { // 文件路径(内部存储路径) mLogFileDir = XLogStoreUtil.getLogFileDir(mContext); mLogFilingDir = XLogStoreUtil.getLogFilingDir(mContext); // 从对应文件夹中 读取 缓存的xlog文件信息 mCurrLogFileInfo = XLogStoreUtil.readXLogInfoFromPath(mLogFileDir); // 路径下 文件未读取到 if (mCurrLogFileInfo == null) { initXLogFileInfo(); } } } }); } } catch (Exception e) { e.printStackTrace(); } } /** * 将log打到文件日志 * * @param tagFromUser * @param msgFromUser */ private void logToFile(String tagFromUser, String msgFromUser, Throwable throwable) { // 路径空 if (mContext == null) { Log.e("XLoger", "context need init"); return; } synchronized (mLockObj) { // 要写入文件的日志信息 String printLogInfo = getFileLogMsg(tagFromUser, msgFromUser, throwable); try { // 待输入的数据 byte[] d = printLogInfo.getBytes("utf-8"); // // Log文件的缓存路径 /data/data/%packetname%/files/xlog_yyyyMMdd_HHmmss.txt String logFilePath = XLogStoreUtil.getLogFilePath(mContext, mCurrLogFileInfo.xLogName); File logFile = new File(logFilePath); /** * 文件归档 */ if (mCurrLogFileInfo.xLogSize > XLogConfig.XLOG_FILE_MAXSIZE) { // 文件归档 String logFilingPath = XLogStoreUtil.getLogFilingPath(mContext, mCurrLogFileInfo.xLogName); File logFilingFile = new File(logFilingPath); logFile.renameTo(logFilingFile); /** * 生成新的文件路径 */ resetLogFileInfo(); /** * 向新文件路径中写入数据 */ logToFile(tagFromUser, msgFromUser, throwable); return; } /** * 创建文件IO流 */ if (mCurrLogFileStream == null) { // 文件存在 if (logFile.exists()) { mCurrLogFileStream = new FileOutputStream(logFile, true); } else { mCurrLogFileStream = new FileOutputStream(logFile); } } /** * 写入日志 */ mCurrLogFileStream.write(d); mCurrLogFileStream.write("\r\n".getBytes()); mCurrLogFileStream.flush(); mCurrLogFileInfo.xLogSize += d.length; } catch (Exception e) { e.printStackTrace(); } } } /** * 组成Log字符串.添加时间信息. * * @param tagFromUser * @param msgFromUser * @return */ private String getFileLogMsg(String tagFromUser, String msgFromUser, Throwable throwable) { // 日期 + 筛选tag + msg StringBuffer sb = new StringBuffer(); sb.append("["); // 添加当前日期 sb.append(TimeUtil.getFormatCurrTime()); sb.append(" "); // 添加筛选tag sb.append(XLogConfig.XLOG_TAG); sb.append(" "); sb.append("] "); // 添加用户tag + 日志msg + Exception sb.append(getConsoleLogMsg(tagFromUser, msgFromUser, throwable)); return sb.toString(); } // ############################################################################# private void initXLogFileInfo() { /** * 创建日志文件路径 */ File fileDir = new File(mLogFileDir); File filingDir = new File(mLogFilingDir); if (!fileDir.exists()) { fileDir.mkdir(); } if (!filingDir.exists()) { filingDir.mkdir(); } /** * 生成日志文件信息 */ resetLogFileInfo(); } private void resetLogFileInfo() { if (mCurrLogFileInfo == null) { mCurrLogFileInfo = new XLogInfoBean(); } // 创建新的缓存文件 mCurrLogFileInfo.xLogName = XLogStoreUtil.genLogFileNameByCurrTime(); mCurrLogFileInfo.xLogSize = 0; // 关闭文件流 closeFileStream(); } private void closeFileStream() { // 关闭文件流 try { if (mCurrLogFileStream != null) { mCurrLogFileStream.close(); mCurrLogFileStream = null; } } catch (Exception e) { e.printStackTrace(); } } // ############################################################################# public static class XLogStoreUtil { // #################################### /** * 从对应文件夹中 读取 缓存的xlog文件信息 * * @param logFileDir * @return */ public static XLogInfoBean readXLogInfoFromPath(String logFileDir) { // 数据bean XLogInfoBean xLogInfoBean = null; // 读取缓存路径中已存在的log文件 File fileDir = new File(logFileDir); if (fileDir.exists()) { final File[] files = fileDir.listFiles(); for (int i = 0; i String fileName = file.getName(); long fileSize = file.length(); if (!TextUtils.isEmpty(fileName) && fileName.startsWith(XLogConfig.XLOG_FILE_NAME_PRE) && fileName.endsWith(XLogConfig.XLOG_FILE_NAME_FORMAT)) { // 赋值 xLogInfoBean = new XLogInfoBean(); xLogInfoBean.xLogName = fileName; xLogInfoBean.xLogSize = fileSize; break; } } } } return xLogInfoBean; } /** * 组装:日志缓存文件夹 路径 * * @param context * @return */ public static String getLogFileDir(Context context) { String logFileDir = ""; if (context == null) { return logFileDir; } // 创建log缓存文件路径 // /data/data/%packetname%/files/xlog/ StringBuffer sb = new StringBuffer(); sb.append(context.getFilesDir().getPath()); sb.append(File.separator); sb.append(XLogConfig.XLOG_FILE_DIR); logFileDir = sb.toString(); return logFileDir; } /** * 组装:日志缓存文件路径 * /data/data/%packetname%/files/xlog/xlog_20201111_111111.txt * * @param fileName xlog_20201111_111111.txt * @return */ public static String getLogFilePath(Context context, String fileName) { // 创建log缓存文件路径 // /data/data/%packetname%/files/log/ StringBuffer sb = new StringBuffer(); sb.append(XLogStoreUtil.getLogFileDir(context)); sb.append(File.separator); sb.append(fileName); return sb.toString(); } /** * 组装:日志归档文件夹 路径(文件超过一定大小后归档到该路径下) * * @param context * @return */ public static String getLogFilingDir(Context context) { if (context == null) { return ""; } StringBuffer sb = new StringBuffer(); sb.append(XLogStoreUtil.getLogFileDir(context)); sb.append(File.separator); sb.append(XLogConfig.XLOG_FILING_DIR); return sb.toString(); } /** * 组装:日志归档文件路径 * /data/data/%packetname%/files/xlog/xlog_20201111_111111.txt * * @param fileName xlog_20201111_111111.txt * @return */ public static String getLogFilingPath(Context context, String fileName) { // 创建log缓存文件路径 // /data/data/%packetname%/files/log/ StringBuffer sb = new StringBuffer(); sb.append(XLogStoreUtil.getLogFilingDir(context)); sb.append(File.separator); sb.append(fileName); return sb.toString(); } /** * 举例 xlog_20201111_111111.txt * * @return */ public static String genLogFileNameByCurrTime() { String currTime = TimeUtil.getFormatCurrTime(); // 生成文件路径 StringBuffer sb = new StringBuffer(); // file name sb.append(XLogConfig.XLOG_FILE_NAME_PRE); sb.append(currTime); sb.append(XLogConfig.XLOG_FILE_NAME_FORMAT); // 打开对应文件 return sb.toString(); } /** * 压缩后的日志文件缓存路径: * /sdcard/Android/data/包名/file/zip_log * * @param context * @return */ public static String genDesZipFilePath(Context context) { StringBuffer sb = new StringBuffer(); // 图片文件夹路径 sb.append(SdCardUtil.getPrivateFilePath(context, XLogConfig.XLOG_ZIP_DIR)); sb.append(File.separator); sb.append(XLogConfig.XLOG_FILE_NAME_PRE); // 以时间命令log文件 sb.append(TimeUtil.getFormatCurrTime()); // 扩展名 sb.append(".zip"); return sb.toString(); } } /** * 时间工具类 */ public static class TimeUtil { /** * 格式化的 当前时间 * * @return 字符串 yyyyMMdd_HHmmss */ public static String getFormatCurrTime() { Date currentTime = new Date(); SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd_HHmmss"); String dateString = formatter.format(currentTime); return dateString; } } /** * 内部存储 * /data/data/包名/files * context.getFilesDir().getPath() * /data/data/包名/cache * context.getCacheDir().getPath() *

* 外部存储 * /sdcard/Android/data/包名/cache/dir * context.getExternalFilesDir("dir").getPath() * /sdcard/Android/data/包名/cache * context.getExternalCacheDir().getPath() */ public static class SdCardUtil { /** * 获取应用私有file目录 *

* /sdcard/Android/data/包名/file/dir * * @param dir The type of files directory to return. May be {@code null} * for the root of the files directory or one of the following * constants for a subdirectory: * {@link Environment#DIRECTORY_MUSIC}, * {@link Environment#DIRECTORY_PODCASTS}, * {@link Environment#DIRECTORY_RINGTONES}, * {@link Environment#DIRECTORY_ALARMS}, * {@link Environment#DIRECTORY_NOTIFICATIONS}, * {@link Environment#DIRECTORY_PICTURES}, or * {@link Environment#DIRECTORY_MOVIES}. */ public static String getPrivateFilePath(Context context, String dir) { File file = context.getExternalFilesDir(dir); //先判断外部存储是否可用 if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && file != null) { return file.getAbsolutePath(); } else { return context.getFilesDir() + File.separator + dir; } } } /** * 文件压缩工具类 */ public static class ZipFileUtil { /** * 多个文件的压缩 * * @param filePaths 文件列表 * @param destZip 压缩后文件 例:abc.zip * @return */ public static boolean exportZipFromPaths(List filePaths, File destZip) { // 空判断 if (filePaths == null || filePaths.isEmpty() || destZip == null) { return false; } // 获取 lastFiles 路径下的全部文件 List exportFiles = new ArrayList(); int size = filePaths.size(); for (int i = 0; i if (TextUtils.isEmpty(path) || exportFiles == null) { return; } exportFiles(exportFiles, new File(path)); } /** * 读取 file 路径下的全部文件 * * @param exportFiles 输出文件列表 * @param file 对应的输入路径 */ private static void exportFiles(List exportFiles, File file) { // 空判断 if (file == null || !file.exists() || exportFiles == null) { return; } // 路径文件 if (!file.isDirectory()) { exportFiles.add(file); } // 文件列表 else { File[] files = file.listFiles(); if (files == null || files.length == 0) { return; } int length = files.length; for (int i = 0; i // 空判断 if (list == null || list.isEmpty() || destZip == null) { return false; } InputStream input = null; ZipOutputStream zipOut = null; // try { // 压缩文件存在,则删除 if (destZip.exists()) { destZip.delete(); } // 创建压缩文件 try { destZip.createNewFile(); } catch (IOException e1) { e1.printStackTrace(); } // 创建文件目录 if (!destZip.getParentFile().exists()) { destZip.getParentFile().mkdir(); } // 压缩文件流 zipOut = new ZipOutputStream(new FileOutputStream(destZip)); // File file = null; byte[] buf = new byte[4096]; // int length = list.size(); for (int i = 0; i input = new FileInputStream(file); zipOut.putNextEntry(new ZipEntry(file.getParentFile().getAbsolutePath() + File.separator + file.getName())); int readCount = 0; while ((readCount = input.read(buf)) > 0) { zipOut.write(buf, 0, readCount); } zipOut.closeEntry(); input.close(); } } zipOut.close(); return true; } catch (Exception e) { e.printStackTrace(); return false; } finally { try { if (input != null) { input.close(); } if (zipOut != null) { zipOut.close(); } } catch (IOException e1) { e1.printStackTrace(); } } } } }



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3