Java lit les fichiers dans le package zip/jar

1、jar contre zip:

Les fichiers jar et les fichiers zip sont des fichiers d'archive et tous deux sont compressés. En fait, les fichiers jar utilisent les mêmes techniques d'archivage et de compression que les fichiers zip. Les fichiers jar sont donc en fait un type spécifique de fichier zip. (Un fichier JAR est essentiellement un fichier zip contenant un répertoire META-INF facultatif.) Tout cela signifie :

  • Vous pouvez ouvrir les fichiers jar avec les mêmes outils que vous utilisez pour ouvrir les fichiers zip
  • les fichiers jar sont un sous-ensemble de fichiers zip, donc un fichier zip peut être utilisé comme fichier jar s'il suit la spécification jar

2. Lisez le fichier compressé zip :

1) Méthode 1 : Lire à partir du fichier via 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); //读取文件内容
		 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) Méthode 2 : lire à partir du flux via ZipInputStream

private static InputStream getInputStream() throws FileNotFoundException {
	File file = new File("/data/testzip.zip");
	InputStream in = new FileInputStream(file);
	return in;
}
//错误方法
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(); // 关闭zipEntry
			}
		}
	} finally {
		zis.close(); //关闭zipInputStream
	}
}

Remarque : IOUtils est utilisé pour lire les données du flux, car la méthode de lecture personnalisée fermera le inputStream passé après la lecture. S'il y a plusieurs fichiers dans le package zip, une erreur sera signalée lors de la lecture du deuxième fichier d'entrée. zipInputStream ne peut être fermé qu'à la fin. Cependant, IOUtils utilise la méthode de copie et ne ferme pas le flux entrant .

3. Les fichiers/répertoires du pot sont pratiques et lisibles :

1) Méthode 1 : utilisez JarFile pour lire le fichier Jar

Semblable à ZipFile, utilisez 'getEntry(String name)' ou 'entires' pour obtenir ZipEntry ou JarEntry (ils peuvent être considérés comme la même chose), puis utilisez "JarFile.getInputStream(ZipEntry ze)" pour obtenir 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) Méthode 2 : lire à partir du flux via JarInputStream (similaire à ZipInputStream)

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(); // 关闭zipEntry
			}
		}
	} finally {
		jis.close(); //关闭zipInputStream
	}
}

3) Méthode 3 : ouvrez une ressource dans un fichier jar via JarURLConnection, puis lisez-la via le flux. 

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();
	}
}

Résumer:

Étant donné que les structures zip et jar sont cohérentes, l'utilisation de ZipFile et JarFile, ZipInputStream et JarInputStream est la même. Il convient de noter qu'en raison de la structure particulière du package zip, le ZipInputStream par défaut ne contient pas de données et ce n'est qu'après avoir appelé la méthode getNextEntry que le contenu de l'entrée correspondante (un fichier dans le package zip) est écrit dans le ZipInputStream. milieu. Dans la mauvaise écriture ci-dessus, vous pouvez voir que les données ne peuvent pas être lues directement à partir de ZipInputStream, uniquement après avoir appelé getNextEntry.

Guess you like

Origin blog.csdn.net/liuxiao723846/article/details/130967940