openplanning

Hướng dẫn nén và giải nén trong Java

  1. Đọc ghi file zip sử dụng java.util.zip
  2. Đọc ghi file jar sử dụng java.util.jar
  3. Xử lý file RAR

1. Đọc ghi file zip sử dụng java.util.zip

Để xử lý các công việc liên quan tới nén và giải nén, JDK cung cấp cho bạn package java.util.zip với một số class để làm việc này.

Đáng tiếc là thư viện này không thể đọc và giải nén các định dạng phổ biến khác như rar, hoặc 7zip. Để giải sử lý các định dạng rar, 7zip, .. bạn cần có một thư viện khác. Trong tài liệu này tôi có để cập tới các thư viện để làm việc này.
Đây là hình ảnh một file zip được mở bằng công cụ Winrar.
java.util.zip coi các file trong file zip là các ZipEntry.
ListZipEntriesDemo.java
package org.o7planning.tutorial.javaiozip;

import java.io.FileInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class ListZipEntriesDemo {

	public static void main(String[] args) {
		String FILE_PATH = "C:/test/datas.zip"; 
		ZipInputStream zipIs = null;
		try {
			// Tạo đối tượng ZipInputStream để đọc file zip.
			zipIs = new ZipInputStream(new FileInputStream(FILE_PATH));

			ZipEntry entry = null;
			// Duyệt từng Entry (Từ trên xuống dưới cho tới hết)
			while ((entry = zipIs.getNextEntry()) != null) {
				if (entry.isDirectory()) {
					System.out.print("Directory: ");
				} else {
					System.out.print("File: ");
				}
				System.out.println(entry.getName());
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				zipIs.close();
			} catch (Exception e) {
			}
		}
	} 
}
Kết quả chạy ví dụ:
Ví dụ giải nén file zip vào một thư mục nào đó:
UnZipDemo.java
package org.o7planning.tutorial.javaiozip;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class UnZipDemo { 
	public static void main(String[] args) {
		final String OUTPUT_FOLDER = "C:/output";
		String FILE_PATH = "C:/test/datas.zip";

		// Tạo thư mục Output nếu nó không tồn tại.
		File folder = new File(OUTPUT_FOLDER);
		if (!folder.exists()) {
			folder.mkdirs();
		}
		// Tạo một buffer (Bộ đệm).
		byte[] buffer = new byte[1024];

		ZipInputStream zipIs = null;
		try {
			// Tạo đối tượng ZipInputStream để đọc file từ 1 đường dẫn (path).
			zipIs = new ZipInputStream(new FileInputStream(FILE_PATH));

			ZipEntry entry = null;
			// Duyệt từng Entry (Từ trên xuống dưới cho tới hết)
			while ((entry = zipIs.getNextEntry()) != null) {
				String entryName = entry.getName();
				String outFileName = OUTPUT_FOLDER + File.separator + entryName;
				System.out.println("Unzip: " + outFileName);

				if (entry.isDirectory()) {
					// Tạo các thư mục.
					new File(outFileName).mkdirs();
				} else {
					// Tạo một Stream để ghi dữ liệu vào file.
					FileOutputStream fos = new FileOutputStream(outFileName);

					int len;
					// Đọc dữ liệu trên Entry hiện tại.
					while ((len = zipIs.read(buffer)) > 0) {
						fos.write(buffer, 0, len);
					} 
					fos.close();
				} 
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				zipIs.close();
			} catch (Exception e) {
			}
		}
	} 
}
Kết quả chạy ví dụ:
Nén thư mục
ZipDirectory.java
package org.o7planning.tutorial.javaiozip;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipDirectory { 
	public ZipDirectory() {

	} 
	// Phương thức dùng để nén một thư mục.
	public void zipDirectory(File inputDir, File outputZipFile) {
		// Tạo thư mục cha cho file đầu ra (output file).
		outputZipFile.getParentFile().mkdirs();

		String inputDirPath = inputDir.getAbsolutePath();
		byte[] buffer = new byte[1024];

		FileOutputStream fileOs = null;
		ZipOutputStream zipOs = null;
		try { 
			List<File> allFiles = this.listChildFiles(inputDir); 
			// Tạo đối tượng ZipOutputStream để ghi file zip.
			fileOs = new FileOutputStream(outputZipFile);
			// 
			zipOs = new ZipOutputStream(fileOs);
			for (File file : allFiles) {
				String filePath = file.getAbsolutePath(); 
				System.out.println("Zipping " + filePath);
				// entryName: is a relative path.
				String entryName = filePath.substring(inputDirPath.length() + 1);

				ZipEntry ze = new ZipEntry(entryName);
				// Thêm entry vào file zip.
				zipOs.putNextEntry(ze);
				// Đọc dữ liệu của file và ghi vào ZipOutputStream.
				FileInputStream fileIs = new FileInputStream(filePath); 
				int len;
				while ((len = fileIs.read(buffer)) > 0) {
					zipOs.write(buffer, 0, len);
				}
				fileIs.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			closeQuite(zipOs);
			closeQuite(fileOs);
		} 
	} 
	private void closeQuite(OutputStream out) {
		try {
			out.close();
		} catch (Exception e) {
		}
	} 
	// Phương thức này trả về danh sách các file,
	// bao gồm tất cả các file con, cháu,.. của thư mục đầu vào.
	private List<File> listChildFiles(File dir) throws IOException {
		List<File> allFiles = new ArrayList<File>();

		File[] childFiles = dir.listFiles();
		for (File file : childFiles) {
			if (file.isFile()) {
				allFiles.add(file);
			} else {
				List<File> files = this.listChildFiles(file);
				allFiles.addAll(files);
			}
		}
		return allFiles;
	} 
	public static void main(String[] args) {
		ZipDirectory zipDir = new ZipDirectory(); 
		File inputDir = new File("C:/datas");
		File outputZipFile = new File("C:/output/datas.zip"); 
		zipDir.zipDirectory(inputDir, outputZipFile); 
	}
}
Kết quả chạy ví dụ:

2. Đọc ghi file jar sử dụng java.util.jar

Về cơ bản việc đọc ghi file jar không có gì khác biệt so với file Zip.
  • JarInputStream mở rộng từ ZipInputStream hỗ trợ thêm tính năng đọc các thông tin MANIFEST.
  • JarOutputStream mở rộng từ ZipOutputStream hỗ trợ thêm tính năng ghi thông tin MANIFEST.
Các file thư viện jar thông thường của java thường có thông tin MANIFEST rất đơn giản.
Ví dụ đây là một file MANIFEST.MF đóng gói trong file jar của 1 ứng dụng RAP có nhiều thông tin hơn:
META-INF/MANIFEST.MF
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: RAPWorkbenchTutorial
Bundle-SymbolicName: RAPWorkbenchTutorial;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: rapworkbenchtutorial.Activator
Require-Bundle: org.eclipse.rap.ui;bundle-version="2.3.0",
org.apache.felix.gogo.command;bundle-version="0.10.0",
org.apache.felix.gogo.runtime;bundle-version="0.10.0",
org.apache.felix.gogo.shell;bundle-version="0.10.0",
org.eclipse.equinox.console;bundle-version="1.1.0",
org.eclipse.equinox.http.jetty;bundle-version="3.0.200",
org.eclipse.equinox.ds;bundle-version="1.4.200",
org.eclipse.rap.rwt.osgi;bundle-version="2.3.0",
org.eclipse.rap.design.example;bundle-version="2.3.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Ví dụ một file jar mở với Winrar:
Các thực thể trong file jar được coi là các JarEntry.
Một ví dụ đơn giản đọc thông tin MANIFEST của file jar. Dưới đây là hình ảnh nội dung của một file Manifest đơn giản.
ReadJarFileDemo.java
package org.o7planning.tutorial.jar;

import java.io.FileInputStream;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;

public class ReadJarFileDemo { 
	public static void main(String[] args) {
		String FILE_PATH = "C:/DevPrograms/Java/jdk1.7.0_45/lib/dt.jar"; 
		JarInputStream zipIs = null;
		try {
			// Tạo đối tượng JarInputStream để đọc file jar.
			zipIs = new JarInputStream(new FileInputStream(FILE_PATH)); 
			// Đọc thông tin Manifest:
			Manifest manifest = zipIs.getManifest();
			Attributes atts = manifest.getMainAttributes();
			String version = atts.getValue("Manifest-Version");
			String createdBy = atts.getValue("Created-By");
			System.out.println("Manifest-Version:" + version);
			System.out.println("Created-By:" + createdBy);
			System.out.println("========================"); 
			JarEntry entry = null;
			// Duyệt từng Entry (Từ trên xuống dưới cho tới hết)
			while ((entry = zipIs.getNextJarEntry()) != null) {
				if (entry.isDirectory()) {
					System.out.print("Folder: ");
				} else {
					System.out.print("File: ");
				}
				System.out.println(entry.getName());
			} 
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				zipIs.close();
			} catch (Exception e) {
			}
		}
	} 
}
Kết quả chạy ví dụ:

3. Xử lý file RAR

Để xử lý file RAR bạn cần một thư viện mã nguồn mở. Bạn có thể sử dụng một trong các thư viện sau, được đánh giá tốt theo thứ tự giảm dần.
Trong tài liệu này tôi sẽ hướng dẫn bạn sử dụng JUnRar (Phiên bản tại thời điểm 9-2014 đang là 0.7)
Download junrar:

Java cơ bản

Show More