From 9cc206cc95ce5a955842012260e2b8f16713cb12 Mon Sep 17 00:00:00 2001 From: DXL <64101226@qq.com> Date: Thu, 27 Aug 2020 12:38:23 +0800 Subject: [PATCH] Add files via upload --- appmain/utils/stream/FileUtils.java | 632 +++++++++++++++++++++++ appmain/utils/stream/IOUtils.java | 31 ++ appmain/utils/stream/LineParseUtils.java | 85 +++ appmain/utils/stream/ZipUtils.java | 207 ++++++++ 4 files changed, 955 insertions(+) create mode 100644 appmain/utils/stream/FileUtils.java create mode 100644 appmain/utils/stream/IOUtils.java create mode 100644 appmain/utils/stream/LineParseUtils.java create mode 100644 appmain/utils/stream/ZipUtils.java diff --git a/appmain/utils/stream/FileUtils.java b/appmain/utils/stream/FileUtils.java new file mode 100644 index 0000000..bc8a1ad --- /dev/null +++ b/appmain/utils/stream/FileUtils.java @@ -0,0 +1,632 @@ +package com.proxgrind.chameleon.utils.stream; + +import android.app.Activity; +import android.app.Application; +import android.content.ActivityNotFoundException; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.media.MediaMetadataRetriever; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.os.ParcelFileDescriptor; +import android.provider.DocumentsContract; +import android.provider.MediaStore; + +import androidx.annotation.NonNull; +import androidx.core.content.FileProvider; +import androidx.loader.content.CursorLoader; + +import android.provider.OpenableColumns; +import android.widget.Toast; + +import com.proxgrind.chameleon.R; +import com.proxgrind.chameleon.utils.system.AppContextUtils; +import com.proxgrind.chameleon.utils.tools.ArrayUtils; +import com.proxgrind.chameleon.utils.system.LogUtils; +import com.proxgrind.chameleon.utils.tools.StringUtils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.URI; +import java.net.URL; +import java.nio.channels.FileChannel; +import java.text.DecimalFormat; +import java.util.ArrayList; + +/* + * 一系列文件操作的封装! + * */ +public class FileUtils { + + // 上下文,用于给File类获取资源! + private static Application context = AppContextUtils.app; + + private static DecimalFormat format = new DecimalFormat("#.00"); + + public interface Size { + long B = 1024; + long KB = B * 1024; + long MB = KB * 1024; + long GB = MB * 1024; + long TB = GB * 1024; + } + + public interface Name { + String B = "B"; + String KB = "KB"; + String MB = "MB"; + String GB = "GB"; + String TB = "TB"; + } + + //获得文件的输入流! + public static FileInputStream getFis(File file) throws FileNotFoundException { + return new FileInputStream(file); + } + + //获得文件的输入流! + public static InputStream getFis(Uri stream) throws FileNotFoundException { + return context.getContentResolver().openInputStream(stream); + } + + //获得文件的输出流! + public static FileOutputStream getFos(File file, boolean append) throws FileNotFoundException { + return new FileOutputStream(file, append); + } + + public static byte[] readBytes(InputStream is, long count, long max, long min) throws IOException { + if (max != -1 && is.available() > max) return null; + if (min != -1 && is.available() < min) return null; + // The length correct. + if (count == -1) count = is.available(); + byte[] buf = new byte[(int) count]; + if (is.read(buf, 0, (int) count) != count) { + IOUtils.close(is); + throw new IOException("read bytes file len is error!"); + } + IOUtils.close(is); + return buf; + } + + public static byte[] readBytes(InputStream is) throws IOException { + // The length correct. + int count = is.available(); + byte[] buf = new byte[(int) count]; + if (is.read(buf, 0, (int) count) != count) { + IOUtils.close(is); + throw new IOException("read bytes file len is error!"); + } + IOUtils.close(is); + return buf; + } + + public static byte[] readBytes(File file) throws IOException { + return readBytes(file, (int) file.length()); + } + + public static byte[] readBytes(File file, long count) throws IOException { + FileInputStream fis = getFis(file); + return readBytes(fis, count, -1, -1); + } + + public static byte[] readBytes(File file, long count, long max, long min) throws IOException { + FileInputStream fis = getFis(file); + return readBytes(fis, count, max, min); + } + + public static byte[] readBytes(Uri uri) throws IOException { + return readBytes(uri, -1); + } + + public static byte[] readBytes(Uri uri, long count) throws IOException { + InputStream fis = getFis(uri); + return readBytes(fis, count, -1, -1); + } + + public static byte[] readBytes(Uri uri, long count, long max, long min) throws IOException { + InputStream fis = getFis(uri); + return readBytes(fis, count, max, min); + } + + //读取文件以每行 + public static String[] readLines(File file) throws IOException { + FileInputStream fileIs; + ArrayList resultList = new ArrayList<>(); + fileIs = new FileInputStream(file); + String tmpBUf; + //创建字符缓冲读取对象 + BufferedReader bReader = new BufferedReader(new InputStreamReader(fileIs)); + while ((tmpBUf = bReader.readLine()) != null) { + resultList.add(tmpBUf); + } + return ArrayUtils.list2Arr(resultList); + } + + //按匹配的行读取文件 + public static String[] readLines(File file, String regex) throws IOException { + String[] resultArray = readLines(file); + ArrayList resultList = new ArrayList<>(); + if (resultArray == null) return new String[0]; + for (String str : resultArray) { + if (str.matches(regex)) { + resultList.add(str); + } + } + return ArrayUtils.list2Arr(resultList); + } + + //写入指定的字节到文件中,以覆盖或者追加的方式! + public static void writeBytes(byte[] data, File file, boolean append) throws IOException { + if (!file.exists()) createFile(file); + if (!file.isFile()) return; + LogUtils.d("写入的目标: " + file.getAbsolutePath()); + FileOutputStream fos = getFos(file, append); + fos.write(data); + } + + //写入指定的字节到文件中,以覆盖或者追加的方式! + public static void writeBytes(byte[] data, FileOutputStream fos) throws IOException { + fos.write(data); + } + + // 写入指定的字节到文件中,适配SAF + public static void writeBytes(byte[] data, Uri target) throws IOException { + OutputStream os = context.getContentResolver().openOutputStream(target); + if (os != null) { + os.write(data); + os.close(); + } + } + + // 写入指定的字节到文件中,适配SAF + public static void writeBytes(File source, Uri target) throws IOException { + writeBytes(readBytes(Uri.fromFile(source)), target); + } + + //使用字符串内容覆盖文件内容 + public static void writeString(File file, String str, boolean append) { + try { + writeBytes(str.getBytes(), file, append); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // 根据文件后缀名获得对应的MIME类型。 + private static String getMimeType(String filePath) { + MediaMetadataRetriever mmr = new MediaMetadataRetriever(); + String mime = "*/*"; + if (filePath != null) { + try { + mmr.setDataSource(filePath); + mime = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE); + } catch (RuntimeException e) { + return mime; + } + } + return mime; + } + + //删除文件夹目录下所有的文件 + public static boolean delete(File dir) { + if (dir.isDirectory()) { + if (dir.delete()) { + return false; + } + String[] files = dir.list(); + if (files == null) { + return dir.delete(); + } + //非空目录,迭代删除所有的文件 + for (String file : files) + delete(new File(dir.getAbsolutePath() + File.separator + file)); + //然后进行目录删除! + return delete(dir); + } else { + return dir.delete(); + } + } + + public static boolean delete(String path) { + return delete(new File(path)); + } + + // 調用系統方法分享文件 + public static void shareFile(Context context, Uri uri) { + Intent share = new Intent(Intent.ACTION_SEND); + //判断是否是AndroidN以及更高的版本 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && + ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {//如果SDK版本>=24,即:Build.VERSION.SDK_INT >= 24 + uri = FileProvider.getUriForFile( + context, + FileUtils.getFileProviderName(), + new File(FileUtils.getFilePathByUri(uri)) + ); + } + share.putExtra(Intent.EXTRA_STREAM, uri); + share.setType("*/*");//此处可发送多种文件 + share.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + //context.startActivity(Intent.createChooser(share, "分享文件")); 会崩溃! + try { + context.startActivity(share); + } catch ( + Exception e) { + e.printStackTrace(); + Toast.makeText(context, R.string.tips_no_app_process, Toast.LENGTH_SHORT).show(); + } + } + + public final static String getFileProviderName() { + return context.getPackageName() + ".fileprovider"; + } + + public static String getFilePathByUri(Uri uri) { + // 以 file:// 开头的 + if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { + return uri.getPath(); + } + // 以/storage开头的也直接返回 + if (isOtherDocument(uri)) { + return uri.getPath(); + } + // 版本兼容的获取! + String path = getFilePathByUri_BELOWAPI11(uri); + if (path != null) { + LogUtils.d("getFilePathByUri_BELOWAPI11获取到的路径为:" + path); + return path; + } + path = getFilePathByUri_API11to18(uri); + if (path != null) { + LogUtils.d("getFilePathByUri_API11to18获取到的路径为:" + path); + return path; + } + path = getFilePathByUri_API19(uri); + LogUtils.d("getFilePathByUri_API19获取到的路径为:" + path); + return path; + } + + private static String getFilePathByUri_BELOWAPI11(Uri uri) { + // 以 content:// 开头的,比如 content://media/extenral/images/media/17766 + if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) { + String path = null; + String[] projection = new String[]{MediaStore.Images.Media.DATA}; + Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null); + if (cursor != null) { + if (cursor.moveToFirst()) { + try { + int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + if (columnIndex > -1) { + path = cursor.getString(columnIndex); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + cursor.close(); + } + return path; + } + return null; + } + + private static String getFilePathByUri_API11to18(Uri contentUri) { + String[] projection = {MediaStore.Images.Media.DATA}; + String result = null; + CursorLoader cursorLoader = new CursorLoader(context, contentUri, projection, null, null, null); + Cursor cursor = cursorLoader.loadInBackground(); + if (cursor != null) { + if (cursor.moveToFirst()) { + try { + int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + result = cursor.getString(column_index); + } catch (Exception e) { + e.printStackTrace(); + } + } + cursor.close(); + } + return result; + } + + private static String getFilePathByUri_API19(Uri uri) { + // 4.4及之后的 是以 content:// 开头的,比如 content://com.android.providers.media.documents/document/image%3A235700 + // content://com.tencent.mtt.fileprovider/QQBrowser/tencent/MobileQQ/photo/_-176177031_Screenshot_20200225_213619_com.tencent.mobileqq_1582637779000_wifi_0.jpg + if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (DocumentsContract.isDocumentUri(context, uri)) { + if (isExternalStorageDocument(uri)) { + // ExternalStorageProvider + String docId = DocumentsContract.getDocumentId(uri); + String[] split = docId.split(":"); + String type = split[0]; + if ("primary".equalsIgnoreCase(type)) { + if (split.length > 1) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } else { + return Environment.getExternalStorageDirectory() + "/"; + } + // This is for checking SD Card + } + } else if (isDownloadsDocument(uri)) { + //下载内容提供者时应当判断下载管理器是否被禁用 + int stateCode = context.getPackageManager().getApplicationEnabledSetting("com.android.providers.downloads"); + if (stateCode != 0 && stateCode != 1) { + return null; + } + String id = DocumentsContract.getDocumentId(uri); + // 如果出现这个RAW地址,我们则可以直接返回! + if (id.startsWith("raw:")) { + return id.replaceFirst("raw:", ""); + } + if (id.contains(":")) { + String[] tmp = id.split(":"); + if (tmp.length > 1) { + id = tmp[1]; + } + } + Uri contentUri = Uri.parse("content://downloads/public_downloads"); + LogUtils.d("测试打印Uri: " + uri); + try { + contentUri = ContentUris.withAppendedId(contentUri, Long.parseLong(id)); + } catch (Exception e) { + e.printStackTrace(); + } + String path = getDataColumn(contentUri, null, null); + if (path != null) return path; + // 兼容某些特殊情况下的文件管理器! + String fileName = getFileNameByUri(context, uri, true); + if (fileName != null) { + path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName; + return path; + } + } else if (isMediaDocument(uri)) { + // MediaProvider + String docId = DocumentsContract.getDocumentId(uri); + String[] split = docId.split(":"); + String type = split[0]; + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + String selection = "_id=?"; + String[] selectionArgs = new String[]{split[1]}; + return getDataColumn(contentUri, selection, selectionArgs); + } + } + } + return null; + } + + public static String getFileNameByUri(Context context, Uri uri, boolean needPath) { + String relativePath = getFileRelativePathByUri_API18(context, uri); + if (relativePath == null) relativePath = ""; + try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) { + if (cursor != null && cursor.moveToFirst()) { + int index = cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME); + String result = cursor.getString(index); + return needPath ? relativePath + result : result; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private static String getFileRelativePathByUri_API18(Context context, Uri uri) { + final String[] projection; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { + projection = new String[]{ + MediaStore.MediaColumns.RELATIVE_PATH + }; + try (Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null)) { + if (cursor != null && cursor.moveToFirst()) { + int index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.RELATIVE_PATH); + return cursor.getString(index); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + return null; + } + + private static String getDataColumn(Uri uri, String selection, String[] selectionArgs) { + final String column = MediaStore.Images.Media.DATA; + final String[] projection = {column}; + try (Cursor cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null)) { + if (cursor != null && cursor.moveToFirst()) { + final int column_index = cursor.getColumnIndexOrThrow(column); + return cursor.getString(column_index); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + private static boolean isOtherDocument(Uri uri) { + // 以/storage开头的也直接返回 + if (uri != null && uri.getPath() != null) { + String path = uri.getPath(); + if (path.startsWith("/storage")) { + return true; + } + if (path.startsWith("/external_files")) { + return true; + } + } + return false; + } + + private static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + private static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } + + public static void createFile(File file) { + try { + if (!file.exists()) file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static boolean createPaths(File file) { + if (!file.exists()) + return file.mkdirs(); + return false; + } + + public static File[] names2Files(String[] fileStrs) { + ArrayList tmp = new ArrayList<>(); + for (String s : fileStrs) { + tmp.add(new File(s)); + } + return tmp.toArray(new File[0]); + } + + public static String[] files2Names(File[] files) { + ArrayList ret = new ArrayList<>(); + if (files != null) { + for (File f : files) { + ret.add(f.getName()); + } + } + return ret.toArray(new String[0]); + } + + public static File getAppFilesDir() { + if (context != null) + return context.getFilesDir(); + return null; + } + + public static File getAppFilesDir(String sub) { + File path = context.getFileStreamPath(sub); + createPaths(path); + return path; + } + + public static File newFile(File dir, String name) { + createPaths(dir); + File ret = new File(dir.getAbsoluteFile() + File.separator + name); + createFile(ret); + return ret; + } + + //判断文件名是否有效! + public static boolean isValidFileName(String name) { + return !StringUtils.isEmpty(name) && !name.contains("/"); + } + + //获得so库的地址! + public static String getNativePath() { + String ss = context.getApplicationInfo().nativeLibraryDir; + if (ss == null) + ss = context.getFilesDir().getPath() + "/lib"; + return ss; + } + + public static boolean moveFile(File file, File path) { + String pathStr = path.getAbsolutePath(); + pathStr = pathStr.endsWith(File.separator) ? pathStr : pathStr + File.separator; + String targetFile = pathStr + file.getName(); + File tmp = new File(targetFile); + createFile(tmp); + if (tmp.exists() && tmp.isFile()) { + // 开始写入! + return file.renameTo(new File(targetFile)); + } + return true; + } + + public static boolean copy(File source, File target) throws IOException { + if (target == null || source == null) return false; + FileChannel inputChannel = null; + FileChannel outputChannel = null; + try { + File parentFile = target.getParentFile(); + if (parentFile != null) { + createPaths(parentFile); + } + createFile(target); + inputChannel = new FileInputStream(source).getChannel(); + outputChannel = new FileOutputStream(target).getChannel(); + outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); + } finally { + IOUtils.close(inputChannel); + IOUtils.close(outputChannel); + } + return true; + } + + public static boolean copy(FileDescriptor descriptor, FileDescriptor target) throws IOException { + if (target == null || descriptor == null) return false; + FileChannel inputChannel = null; + FileChannel outputChannel = null; + try { + inputChannel = new FileInputStream(descriptor).getChannel(); + outputChannel = new FileOutputStream(target).getChannel(); + outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); + } finally { + IOUtils.close(inputChannel); + IOUtils.close(outputChannel); + } + return true; + } + + public static boolean copy(byte[] rawData, File target) { + try { + writeBytes(rawData, target, false); + return true; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + + public static String getFileCountIfFolder(File[] files) { + if (files == null) files = new File[0]; + return files.length + " " + context.getString(R.string.item); + } + + public static String getFileLengthIfFile(@NonNull File file) { + long length = file.length(); + String fileLength; + if (length < Size.B) { + fileLength = length + Name.B; + } else if (length < Size.KB) { + fileLength = format.format(length * 1.0 / Size.B) + Name.KB; + } else if (length < Size.MB) { + fileLength = format.format(length * 1.0 / Size.KB) + Name.MB; + } else if (length < Size.GB) { + fileLength = format.format(length * 1.0 / Size.MB) + Name.GB; + } else { + fileLength = format.format(length * 1.0 / Size.GB) + Name.TB; + } + return fileLength; + } +} diff --git a/appmain/utils/stream/IOUtils.java b/appmain/utils/stream/IOUtils.java new file mode 100644 index 0000000..4caffdd --- /dev/null +++ b/appmain/utils/stream/IOUtils.java @@ -0,0 +1,31 @@ +package com.proxgrind.chameleon.utils.stream; + +import androidx.annotation.Nullable; + +import java.io.Closeable; +import java.io.Flushable; +import java.io.IOException; + +public class IOUtils { + public static boolean close(@Nullable Closeable closeable) { + if (closeable == null) return false; + try { + closeable.close(); + return true; + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + + public static boolean flush(@Nullable Flushable flushable) { + if (flushable == null) return false; + try { + flushable.flush(); + return true; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } +} diff --git a/appmain/utils/stream/LineParseUtils.java b/appmain/utils/stream/LineParseUtils.java new file mode 100644 index 0000000..8443f55 --- /dev/null +++ b/appmain/utils/stream/LineParseUtils.java @@ -0,0 +1,85 @@ +package com.proxgrind.chameleon.utils.stream; + +import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; + +public class LineParseUtils extends Thread { + + private String LOG_TAG = this.getClass().getSimpleName(); + + /* + * 回调接口,当有完整的一行出现时回调! + * */ + public interface OnNewLineLisenter { + void onNewLine(String str); + } + + //队列,生产消费! + private Queue mConsoleQueue = new LinkedBlockingQueue<>(); + //回调接口! + private OnNewLineLisenter mLisenter; + //标志,是否暂停! + private volatile boolean mPauseLabel = false; + //标志,是否结束! + private volatile boolean mCancelLabel = false; + + public LineParseUtils(OnNewLineLisenter lisenter) { + mLisenter = lisenter; + } + + @Override + public void run() { + //迭代队列 + StringBuilder sb = new StringBuilder(256); + while (!mCancelLabel) { + if (mPauseLabel) { + //Log.d(LOG_TAG, "DynamicLineParseThread is pause!"); + continue; + } + if (mConsoleQueue.size() == 0) continue; + if (mLisenter != null) { + Character c; + while ((c = mConsoleQueue.poll()) != null) { + //遇到的是换行符,则需要处理换行符! + if (c == '\n') { + //回调之前的结果! + String s = sb.toString(); + //Log.d("****", "DLPU新行: " + s); + //开始回调! + mLisenter.onNewLine(s); + //清除缓存,重新建立对象! + sb = new StringBuilder(256); + //尝试通知GC + System.gc(); + //直接跳过下一步的换行符添加! + break; + } + //否则一直追加进缓冲区 + sb.append((char) c); + //Log.d("****", "DLPU: " + sb.toString()); + } + } + } + } + + @Override + public synchronized void start() { + //处理启动相关的实现! + mPauseLabel = false; + if (!isAlive()) { + super.start(); + } + } + + public synchronized void appendText(Character txt) { + mConsoleQueue.add(txt); + } + + public synchronized void pause() { + mPauseLabel = true; + } + + public synchronized void cancel() { + mCancelLabel = true; + } +} diff --git a/appmain/utils/stream/ZipUtils.java b/appmain/utils/stream/ZipUtils.java new file mode 100644 index 0000000..2e1a58b --- /dev/null +++ b/appmain/utils/stream/ZipUtils.java @@ -0,0 +1,207 @@ +package com.proxgrind.chameleon.utils.stream; + +import android.util.Log; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +public class ZipUtils { + public static final String TAG = "ZIP"; + + private ZipUtils() { + + } + + /** + * 解压zip到指定的路径 + * + * @param zipFileString ZIP的名称 + * @param outPathString 要解压缩路径 + * @throws Exception + */ + public static void unZipFolder(String zipFileString, String outPathString) throws Exception { + ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString)); + ZipEntry zipEntry; + String szName = ""; + while ((zipEntry = inZip.getNextEntry()) != null) { + szName = zipEntry.getName(); + if (zipEntry.isDirectory()) { + //获取部件的文件夹名 + szName = szName.substring(0, szName.length() - 1); + File folder = new File(outPathString + File.separator + szName); + folder.mkdirs(); + } else { + Log.e(TAG, outPathString + File.separator + szName); + File file = new File(outPathString + File.separator + szName); + if (!file.exists()) { + Log.e(TAG, "Create the file:" + outPathString + File.separator + szName); + file.getParentFile().mkdirs(); + file.createNewFile(); + } + // 获取文件的输出流 + FileOutputStream out = new FileOutputStream(file); + int len; + byte[] buffer = new byte[1024]; + // 读取(字节)字节到缓冲区 + while ((len = inZip.read(buffer)) != -1) { + // 从缓冲区(0)位置写入(字节)字节 + out.write(buffer, 0, len); + out.flush(); + } + out.close(); + } + } + inZip.close(); + } + + public static void unZipFolder(String zipFileString, String outPathString, String szName) throws Exception { + ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString)); + ZipEntry zipEntry; + while ((zipEntry = inZip.getNextEntry()) != null) { + //szName = zipEntry.getName(); + if (zipEntry.isDirectory()) { + //获取部件的文件夹名 + szName = szName.substring(0, szName.length() - 1); + File folder = new File(outPathString + File.separator + szName); + folder.mkdirs(); + } else { + Log.e(TAG, outPathString + File.separator + szName); + File file = new File(outPathString + File.separator + szName); + if (!file.exists()) { + Log.e(TAG, "Create the file:" + outPathString + File.separator + szName); + file.getParentFile().mkdirs(); + file.createNewFile(); + } + // 获取文件的输出流 + FileOutputStream out = new FileOutputStream(file); + int len; + byte[] buffer = new byte[1024]; + // 读取(字节)字节到缓冲区 + while ((len = inZip.read(buffer)) != -1) { + // 从缓冲区(0)位置写入(字节)字节 + out.write(buffer, 0, len); + out.flush(); + } + out.close(); + } + } + inZip.close(); + } + + /** + * 压缩文件和文件夹 + * + * @param srcFileString 要压缩的文件或文件夹 + * @param zipFileString 压缩完成的Zip路径 + * @throws Exception + */ + public static void zipFolder(String srcFileString, String zipFileString, FilenameFilter filter) throws Exception { + //创建ZIP + ZipOutputStream outZip = new ZipOutputStream(new FileOutputStream(zipFileString)); + //创建文件 + File file = new File(srcFileString); + //压缩 + zipFiles(file.getParent() + File.separator, file.getName(), outZip, filter); + //完成和关闭 + outZip.finish(); + outZip.close(); + } + + /** + * 压缩文件 + * + * @param folderString + * @param fileString + * @param zipOutputSteam + * @throws Exception + */ + private static void zipFiles(String folderString, String fileString, ZipOutputStream zipOutputSteam, FilenameFilter filter) throws Exception { + if (zipOutputSteam == null) + return; + File file = new File(folderString + fileString); + if (file.isFile()) { + ZipEntry zipEntry = new ZipEntry(fileString); + FileInputStream inputStream = new FileInputStream(file); + zipOutputSteam.putNextEntry(zipEntry); + int len; + byte[] buffer = new byte[4096]; + while ((len = inputStream.read(buffer)) != -1) { + zipOutputSteam.write(buffer, 0, len); + } + zipOutputSteam.closeEntry(); + } else { + //文件夹 + String[] fileList = file.list(filter); + if (fileList != null) { + //没有子文件和压缩 + if (fileList.length <= 0) { + ZipEntry zipEntry = new ZipEntry(fileString + File.separator); + zipOutputSteam.putNextEntry(zipEntry); + zipOutputSteam.closeEntry(); + } + //子文件和递归 + for (String s : fileList) { + zipFiles(folderString, fileString + File.separator + s, zipOutputSteam, filter); + } + } + } + } + + /** + * 返回zip的文件输入流 + * + * @param zipFileString zip的名称 + * @param fileString ZIP的文件名 + * @return InputStream + * @throws Exception + */ + public static InputStream upZip(String zipFileString, String fileString) throws Exception { + ZipFile zipFile = new ZipFile(zipFileString); + ZipEntry zipEntry = zipFile.getEntry(fileString); + return zipFile.getInputStream(zipEntry); + } + + /** + * 返回ZIP中的文件列表(文件和文件夹) + * + * @param zipFileString ZIP的名称 + * @param bContainFolder 是否包含文件夹 + * @param bContainFile 是否包含文件 + * @return + * @throws Exception + */ + public static List getFileList(String zipFileString, boolean bContainFolder, boolean bContainFile) throws Exception { + List fileList = new ArrayList(); + ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString)); + ZipEntry zipEntry; + String szName; + while ((zipEntry = inZip.getNextEntry()) != null) { + szName = zipEntry.getName(); + if (zipEntry.isDirectory()) { + // 获取部件的文件夹名 + szName = szName.substring(0, szName.length() - 1); + File folder = new File(szName); + if (bContainFolder) { + fileList.add(folder); + } + } else { + File file = new File(szName); + if (bContainFile) { + fileList.add(file); + } + } + } + inZip.close(); + return fileList; + } +}