java讀取zip/jar包中文件的幾種方式
1、jar vs zip:
jar 文件和 zip 文件都是歸檔文件,并且都經(jīng)過壓縮。事實(shí)上,jar 文件使用與 zip 文件相同的存檔和壓縮技術(shù),所以 jar 文件實(shí)際上是一種特定類型的 zip 文件。(JAR 文件本質(zhì)上是一個(gè)包含可選 META-INF 目錄的 zip 文件。)這一切都意味著:
- 您可以使用與打開 zip 文件相同的工具打開 jar 文件
- jar 文件是 zip 文件的子集,因此如果 zip 文件遵循 jar 規(guī)范,則它可以用作 jar 文件
2、讀取zip壓縮文件:
1)方法一:通過ZipFile從文件中讀取
private static void readZipFile() { try (ZipFile zipFile = new ZipFile("/data/testzip.zip");) { Enumeration<? extends ZipEntry> entries = zipFile.entries(); while(entries.hasMoreElements()){ ZipEntry entry = entries.nextElement(); System.out.println("fileName:"+entry.getName()); //文件名 InputStream stream = zipFile.getInputStream(entry); //讀取文件內(nèi)容 read(stream); } } catch(Exception e) {} //zipFile.close(); } private static void read(InputStream in) { try (InputStreamReader reader = new InputStreamReader(in, "UTF-8"); BufferedReader br = new BufferedReader(reader);) { String con = null; while ((con = br.readLine()) != null) { System.out.println(con); } } catch (Exception e) {} }
2)方法二:通過ZipInputStream從流中讀取
private static InputStream getInputStream() throws FileNotFoundException { File file = new File("/data/testzip.zip"); InputStream in = new FileInputStream(file); return in; } //錯(cuò)誤方法 private static void readZipInputStream() throws FileNotFoundException, IOException { InputStream zippedIn = getInputStream(); // zip壓縮文件流 ZipInputStream zis = new ZipInputStream(zippedIn); read(zis); //讀取的是空 } //正確方法 private static void readZipInputStream2() throws FileNotFoundException, IOException { InputStream zipFileInput = getInputStream(); // zip壓縮文件流 ZipInputStream zis = new ZipInputStream(zipFileInput); ZipEntry entry = null; try { while ((entry = zis.getNextEntry()) != null) { try { final String name = entry.getName(); System.out.println("fileName:"+name); String content = IOUtils.toString(zis); System.out.println(content); } finally { zis.closeEntry(); // 關(guān)閉zipEntry } } } finally { zis.close(); //關(guān)閉zipInputStream } }
注意:在從流中讀取數(shù)據(jù)是使用了IOUtils,原因是自定義read方法讀取完后會(huì)把傳遞進(jìn)來的inputStream給關(guān)閉了。如果zip包中有多個(gè)文件,那么在讀取第二個(gè)entry文件時(shí)就會(huì)報(bào)錯(cuò)。zipInputStream只能在最后關(guān)閉。而IOUtils使用了copy的方式,不會(huì)關(guān)閉傳入的流。
3、jar中文件/目錄便利,以及讀?。?/h2>
1)方法一:使用JarFile讀取Jar文件
和ZipFile類似,使用'getEntry(String name)'或'entires'獲得ZipEntry或JarEntry(它們可以看作同一東西),接下來使用" JarFile.getInputStream(ZipEntry ze)"將其用于獲取InputStream
static void test1() { String path = "/Users/liuxiao/maven-rep/org/apache/thrift/libthrift/0.9.0/libthrift-0.9.0.jar"; try (JarFile jarFile = new JarFile(new File(path));) { Enumeration<JarEntry> entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String entryName = entry.getName(); if (!entry.isDirectory() && entryName.equals("org/apache/thrift/TBase.java")) { System.out.println(entryName);// org/apache/thrift/EncodingUtils.class read(jarFile.getInputStream(entry)); } } } catch (Exception e) { } //使用stream api try (Stream<JarEntry> stream = new JarFile(new File(path)).stream();) { stream .filter(entry -> !entry.isDirectory() && entry.getName().endsWith(".class")) .forEach(entry -> System.out.println(entry.getName())); } catch(Exception e) { } }
2)方法二:通過JarInputStream從流中讀?。ê蚙ipInputStream類似)
private static InputStream getJarFileInputStream() throws FileNotFoundException { File file = new File("/data/mvn_repo/commons-lang/commons-lang/2.1/commons-lang-2.1.jar"); InputStream in = new FileInputStream(file); return in; } private static void readJarInputStream2() throws FileNotFoundException, IOException { InputStream zipFileInput = getJarFileInputStream(); // jar包流 JarInputStream jis = new JarInputStream(zipFileInput); JarEntry entry = null; try { while ((entry = jis.getNextJarEntry()) != null) { try { if (entry.isDirectory()) { continue; } final String name = entry.getName(); System.out.println("fileName:"+name); String content = IOUtils.toString(jis); System.out.println(content); } finally { jis.closeEntry(); // 關(guān)閉zipEntry } } } finally { jis.close(); //關(guān)閉zipInputStream } }
3)方法三:通過JarURLConnection來打開一個(gè)jar中的資源,然后通過流來讀取
static void test2() throws Exception { String filePath = "/Users/liuxiao/maven-rep/org/apache/thrift/libthrift/0.9.0/libthrift-0.9.0.jar"; String name = "org/apache/thrift/TBase.java"; URL url = new URL("jar:file:" + filePath + "!/" + name); JarURLConnection jarConnection = (JarURLConnection) url.openConnection(); try (InputStream in = jarConnection.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));) { String con = null; while ((con = br.readLine()) != null) { System.out.println(con); } } catch (Exception e) { e.printStackTrace(); } }
總結(jié):
由于zip和jar結(jié)構(gòu)時(shí)一致的,所以ZipFile和JarFile,ZipInputStream和JarInputStream的使用方法是一樣的。需要說明的一點(diǎn)是,由于zip包的這種特殊結(jié)構(gòu),默認(rèn)ZipInputStream中是不包含數(shù)據(jù)的,只有在調(diào)用getNextEntry方法后,才回把對(duì)應(yīng)的entry(zip包中的一個(gè)文件)內(nèi)容寫入到ZipInputStream中。上面的一個(gè)錯(cuò)誤寫法中,可以看到直接從ZipInputStream中讀不到數(shù)據(jù),只有調(diào)用getNextEntry后才可以。
到此這篇關(guān)于java讀取zip/jar包中文件的幾種方式的文章就介紹到這了,更多相關(guān)java讀取zip/jar包文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot中Reactor模型的基本概念和最佳實(shí)踐
Reactor模型是一種基于事件驅(qū)動(dòng)和非阻塞IO的編程模型,用于處理并發(fā)和異步操作,本文將介紹Spring Boot中使用Reactor模型的基本概念和最佳實(shí)踐,幫助讀者更好地理解如何利用這一強(qiáng)大的工具來構(gòu)建現(xiàn)代化的Java應(yīng)用程序,感興趣的朋友跟隨小編一起看看吧2024-05-05利用Spring Boot創(chuàng)建docker image的完整步驟
這篇文章主要給大家介紹了關(guān)于如何利用Spring Boot創(chuàng)建docker image的完整步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08spring注解 @PropertySource配置數(shù)據(jù)源全流程
這篇文章主要介紹了spring注解 @PropertySource配置數(shù)據(jù)源全流程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03Java 并發(fā)編程之ThreadLocal詳解及實(shí)例
這篇文章主要介紹了Java 并發(fā)編程之ThreadLocal詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02Springboot結(jié)合@validated優(yōu)化代碼驗(yàn)證
這篇文章主要介紹了Springboot與@validated注解結(jié)合從而實(shí)現(xiàn)讓你的代碼驗(yàn)證更清爽,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08springboot使用filter獲取自定義請(qǐng)求頭的實(shí)現(xiàn)代碼
這篇文章主要介紹了springboot使用filter獲取自定義請(qǐng)求頭的實(shí)例代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05Java實(shí)現(xiàn)京東聯(lián)盟API數(shù)據(jù)獲取功能
這篇文章介紹了Java獲取京東聯(lián)盟API數(shù)據(jù)的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07Springboot調(diào)整接口響應(yīng)返回時(shí)長(zhǎng)詳解(解決響應(yīng)超時(shí)問題)
當(dāng)后端對(duì)于數(shù)據(jù)量較大的處理或是某些耗時(shí)的操作時(shí),需要先對(duì)請(qǐng)求接口的請(qǐng)求進(jìn)行響應(yīng),下面這篇文章主要給大家介紹了關(guān)于Springboot調(diào)整接口響應(yīng)返回時(shí)長(zhǎng)(解決響應(yīng)超時(shí)問題)的相關(guān)資料,需要的朋友可以參考下2023-01-01