java學習筆記:使用zip api進行檔案解壓縮以及不解壓直接讀取指定檔案內容

來源:互聯網
上載者:User

在一個android項目中使用到了zip進行檔案的傳輸,可以大大減少儲存空間和傳輸串流量,於是就會涉及到zip檔案的加壓縮問題。下面將會詳細介紹java原生的zip api。先來簡單列舉一下java中關於zip的api: 一、zip壓縮

java通過 ZipOutputStream 對zip檔案建立輸出資料流,可以使用以下構造方法:

FileOutputStream fos = new FileOutputStream(outFile);ZipOutputStream zos = new ZipOutputStream(fos);

建立了對zip檔案的輸出資料流之後,我們需要逐個寫入需要壓縮的檔案,通過 ZipOutputStream 的 putNextEntry(ZipEntry e)  方法,可以在建立zip檔案內建立需要寫入的下一個檔案的“入口”。

ZipEntry 可以調用其構造方法  ZipEntry(String name)  為要寫入的檔案制定名字name,該名字包含此檔案相對於zip檔案的子目錄。

舉例如下:

如果我們希望將t.txt檔案打包到zip檔案中,並且是打包到zip檔案中的“dir”檔案夾中,那麼就需要指定其 ZipEntry 的構造方法的name為 “dir/t.txt”。如果是直接打包到zip檔案的一級目錄中,那麼就只需要指定name為“t.txt”即可。

下面給出一段壓縮某個檔案到zip的代碼:


ze = new ZipEntry(subPath);zos.putNextEntry(ze);bis = new BufferedInputStream(new FileInputStream(f));while (bis.read(data, 0, byteLength) != -1) {zos.write(data);}bis.close();zos.closeEntry();



上述代碼中subPath是被壓縮檔在zip檔案中的目錄+名字,每次在開啟一個 ZipEntry 之後,在寫入/讀取操作完成以後,都需要將該 ZipEntry 關閉。向zip檔案中寫入檔案的方法跟普通寫檔案相同,使用 BufferedInputStream 進行位元組流寫入操作即可。如果要壓縮的是目錄,那麼就將該目錄下的檔案枚舉進行壓縮,在 ZipEntry 的name中指定其上級目錄即可。

下面給出完整的zip壓縮代碼:


public class ZipLoader {static int byteLength = 1024;public ZipLoader() {}/** * 壓縮檔 * @param files 需要壓縮的檔案/目錄 * @param outFile 壓縮輸出地zip檔案的名字 * @return 壓縮是否成功  * @throws FileNotFoundException * @throws IOException */public static boolean zip(File[] files, String outFile) throws FileNotFoundException, IOException{File file = new File(outFile);String zipPath = file.getAbsolutePath();zipPath = zipPath.substring(0, zipPath.length()-File.separator.length()-outFile.length());// 建立壓縮檔if (!file.exists()) {file.createNewFile();}FileOutputStream fos = new FileOutputStream(outFile);ZipOutputStream zos = new ZipOutputStream(fos);// 壓縮pack(zipPath, files, zos);zos.flush();zos.close();return true;}/** * 打包檔案/目錄 * @param srcPath zip檔案的絕對路徑 * @param files 要打包的檔案/目錄 * @param zos 已串連到zip檔案的zip輸入資料流執行個體 * @throws FileNotFoundException * @throws IOException */private static void pack(String srcPath, File[] files, ZipOutputStream zos) throws FileNotFoundException, IOException {BufferedInputStream bis;ZipEntry ze;byte[] data = new byte[byteLength];for (File f : files) {// 遞迴壓縮目錄if (f.isDirectory()) {pack(srcPath, f.listFiles(), zos);} else if (f.getName().indexOf(".Ds_Store") != -1) {continue;} else {// 擷取被壓縮檔相對zip檔案的路徑String subPath = f.getAbsolutePath();int index = subPath.indexOf(srcPath);if (index != -1) {subPath = subPath.substring(srcPath.length()+File.separator.length());}// 壓縮檔ze = new ZipEntry(subPath);zos.putNextEntry(ze);bis = new BufferedInputStream(new FileInputStream(f));while (bis.read(data, 0, byteLength) != -1) {zos.write(data);}bis.close();zos.closeEntry();}}}}

上述ZipLoader類中的zip方法是調用pack方法進行zip壓縮的,在pack方法中,如果要壓縮的檔案是一個目錄,那麼就對該目錄下的檔案進行pack遞迴調用。


二、zip解壓

ZipFile 提供了entries() 方法得到zip檔案的ZipEntry枚舉,然後就可以根據ZipEntry的getName() 方法得到其相對zip檔案的目錄及檔案名稱,再通過 BufferedOutputStream 和 BufferedInputStream 讀寫檔案即可。

/** * 解壓zip檔案 * @param zipFile 要解壓的zip檔案對象 * @param unzipFilePath 解壓目的絕對路徑 * @throws IOException */@SuppressWarnings("unchecked")public static void unzip(File zipFile, String unzipFilePath) throws IOException {ZipFile zip = new ZipFile(zipFile);Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.entries();ZipEntry ze;String unzipEntryPath;String unzipEntryDirPath;int index;File unzipEntryDir;BufferedOutputStream bos;BufferedInputStream bis;byte[] data = new byte[byteLength];// 建立解壓後的檔案夾File unzipDir = new File(unzipFilePath);if (!unzipDir.exists() || !unzipDir.isDirectory()) {unzipDir.mkdir();}// 解壓while (entries.hasMoreElements()) {// 擷取下一個解壓檔案ze = (ZipEntry) entries.nextElement();unzipEntryPath = unzipFilePath + File.separator + ze.getName();index = unzipEntryPath.lastIndexOf(File.separator);// 擷取解壓檔案上層目錄if (index != -1) {unzipEntryDirPath = unzipEntryPath.substring(0, index);} else {unzipEntryDirPath = "";}// 建立解壓檔案上層目錄unzipEntryDir = new File(unzipEntryDirPath);if (!unzipEntryDir.exists() || !unzipEntryDir.isDirectory()) {unzipEntryDir.mkdir();}// 寫出解壓檔案bos = new BufferedOutputStream(new FileOutputStream(unzipEntryPath));bis = new BufferedInputStream(zip.getInputStream(ze));while (bis.read(data, 0, byteLength) != -1) {bos.write(data);}bis.close();bos.flush();bos.close();}zip.close();}

三、不解壓直接讀取zip檔案內指定檔案的內容

有了第二部分解壓的代碼以後,要讀取指定檔案的內容並不困難,直接上代碼。

/** * 讀取zip檔案中制定檔案的內容 * @param zipFile 目標zip檔案對象 * @param readFileName 目標讀取檔案名稱字 * @return 檔案內容 * @throws ZipException * @throws IOException */@SuppressWarnings("unchecked")public static String getZipFileContent(File zipFile, String readFileName) throws ZipException, IOException {StringBuilder content = new StringBuilder();ZipFile zip = new ZipFile(zipFile);Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.entries();ZipEntry ze;// 枚舉zip檔案內的檔案/while (entries.hasMoreElements()) {ze = entries.nextElement();// 讀取目標對象if (ze.getName().equals(readFileName)) {Scanner scanner = new Scanner(zip.getInputStream(ze));while (scanner.hasNextLine()) {content.append(scanner.nextLine());}scanner.close();}}zip.close();return content.toString();}




相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.