Zip decompression Chinese garbled solution and using ant to implement zip decompression

Source: Internet
Author: User
Tags constructor deflater extract zip file parent directory zip zip folder
Reason:Java's encoding of text is based on Unicode, so if you use Zipinputstream and Zipoutputstream to handle compression and decompression, and you run into a Chinese filename or path, then of course it's Unicode. However, the current compression and decompression software, such as WinZip, does not support Unicode, and it does not handle a file that is encoded in Unicode with a filename.
So how do you make the compression files that WinZip can handle? There are two ways of doing this: one is to use Apache Ant implementation Zip decompression, the other is to modify the JDK with the Zip tool class source code because ant inside is multithreading reads a file, the decompression file is disorderly, but the efficiency is obviously much higher than JDK's zip way. It is recommended that you use Ant's Zip implementation.
The first use of the ant implementation of the zip decompression, where the uncompressed garbled attention to usepublic void UnZip (String unzipfilename,string OutputPath) where this.zipfile = new ZipFile (unzipfilename, "GB18030");Is the key to solve the Chinese name garbled.
Import java.io.*;
Import org.apache.tools.zip.*;

Import java.util.Enumeration; /** *<p> * <b> features: Zip compression, decompression (supporting Chinese filename) </b> *<p> * Description: Using the Zip tool provided by Apache Ant Org.apache.tools.zip Implementation Zi
 P compression and decompression function.
 * Solved the problem because the Java.util.zip package does not support Chinese characters.
	* * @author Winty * @modifier Vernon.zheng/public class Antzip {private ZipFile zipfile; Private Zipoutputstream zipout;
	Compressed zip private zipentry zipentry; private static int bufsize;
	Size of bytes private byte[] buf;
	private int readedbytes; Used in compression.
	The absolute parent path to be removed in order to change the absolute path to a relative path.

	Private String deleteabsoluteparent; /** * Construction method.
	 The default buffer size is 512 bytes.
	* * Public Antzip () {this (512);
	 }/** * Construction method.
		* * @param bufsize * Specifies the buffer size when compressed or uncompressed * * * public antzip (int bufsize) {this.bufsize = bufsize;
		This.buf = new Byte[this.bufsize];
	Deleteabsoluteparent = null;
	 /** * Compresses all files and directories within the folder. * * @param zipdirectory * folder name to compress/public void Dozip (String zipdirectory) {File Zipdir = new Fil E(zipdirectory);
	Dozip (new file[] {zipdir}, Zipdir.getname ()); /** * Compresses multiple files or directories. You can specify multiple separate files or directories.
	 The <code>dozip (String zipdirectory) </code> * Compresses the entire folder directly.
	 * * @param files * A <code>File</code> array consisting of a file or directory to compress.
	 * @param zipfilename * Compressed ZIP file name, if suffix is not ". zip", automatically add suffix ". zip". */public void Dozip (file[] files, String zipfilename) {//No compressed file name specified, default to "ZipFile" if (Zipfilename = null | | zipfilen

		Ame.equals ("")) Zipfilename = "ZipFile";

		Add the ". zip" suffix if (!zipfilename.endswith (". zip")) Zipfilename + = ". zip";
			try {this.zipout = new Zipoutputstream (new Bufferedoutputstream (New FileOutputStream (Zipfilename));
			Compressfiles (Files, this.zipout, true);
		This.zipOut.close ();
		catch (IOException IoE) {ioe.printstacktrace (); }/** * compresses files and directories.            Called by Dozip () * * @param files * The file to be compressed * @param zipout * Zip output stream * @param isabsolute * is the root path of the absolute path to be removed. Because CompressfilES () * will be called recursively, so use deleteabsoluteparent only. You must use Isabsolute to indicate that * compressfiles () is the first call, not a subsequent recursive call. That is, if the path to be compressed is * E:\temp, then the first call, Isabsolute=true, then the deleteabsoluteparent will record * The path to delete is e:\, when compressed subdirectory e:\t When Emp\folder, Isabsolute=false, * then recursively calls Compressfiles (), Deleteabsoluteparent is still e:\. This ensures that the E:\temp and its subdirectories are correctly converted to relative directories. This compression is not an error.
	 Otherwise the absolute path e:\ will also be written to the compressed file. * private void Compressfiles (file[] files, Zipoutputstream zipout, Boolean isabsolute) throws IOException {for (F Ile file:files) {if (file = = null) continue;//Empty Files object//delete Absolute parent path if (File.isabsolute ()) {if (ISABSO
					lute) {deleteabsoluteparent = File.getparentfile (). GetAbsolutePath ();
				Deleteabsoluteparent = Appendseparator (deleteabsoluteparent);

			} else Deleteabsoluteparent = "";
			if (File.isdirectory ()) {//Is the directory Compressfolder (file, zipout);
			else {//is the file Compressfile (files, zipout);
	}
		}
	}

	/** * Compressed files or empty directories.
	 Called by Compressfiles ().  * @param file * @param zipout * Zip output stream/public void Compressfile

		Zipoutputstream zipout) throws IOException {String fileName = file.tostring (); /* Remove absolute parent path.
		*/if (File.isabsolute ()) FileName = Filename.substring (Deleteabsoluteparent.length ());

		if (filename = = NULL | | filename = = "") return; * * * because it is an empty directory, add a "/" at the end. Otherwise it will be treated as an empty file.
		 In the Isdirectory () method of ZipEntry, the directory ends with "/".
		 * Org.apache.tools.zip.ZipEntry:public Boolean isdirectory () {return * GetName (). EndsWith ("/");}

		*/if (file.isdirectory ()) filename = filename + "/";//"\" Zipout.putnextentry (new ZipEntry (FileName) is not available here;
		If it is a file, read it, and if it is an empty directory, you do not need to read it and go directly to Zipout.closeentry ().
			if (File.isfile ()) {FileInputStream Filein = new FileInputStream (file);
			while ((This.readedbytes = Filein.read (this.buf)) > 0) {zipout.write (this.buf, 0, this.readedbytes);
		} filein.close (); } zipout.closeentRy (); /** * Recursively completes the directory file read.
	 Called by Compressfiles (). * @param dir * The file object to be processed * @param zipout * Zip output stream/private void Compressfolder (file D

		IR, Zipoutputstream zipout) throws IOException {file[] files = dir.listfiles ();
			if (Files.length = = 0)//If the directory is empty, the empty directory is compressed individually.
		Compressfile (dir, zipout);
			else//If the directory is not empty, the directories and files are processed separately.
	Compressfiles (Files, zipout, false);
	 /** * Extract the specified zip file. * * @param unzipfilename * ZIP file name needed to be unzipped * * * public void UnZip (String unzipfilename) {FileOutputStream
		Fileout;
		File file;

		InputStream InputStream;

			try {this.zipfile = new ZipFile (unzipfilename); For (Enumeration entries = This.zipFile.getEntries (); entries. hasMoreElements ();)
				{ZipEntry entry = (zipentry) entries.nextelement ();

				File = new file (Entry.getname ());
				if (Entry.isdirectory ()) {//is a directory, the File.mkdirs () is created;
					else {//is a file//if the parent directory of the specified file does not exist, it is created.
		File parent = File.getparentfile ();			if (parent!= null &&!parent.exists ()) {parent.mkdirs ());

					} InputStream = Zipfile.getinputstream (entry);
					Fileout = new FileOutputStream (file);
					while ((This.readedbytes = Inputstream.read (this.buf)) > 0) {fileout.write (this.buf, 0, this.readedbytes);

					} fileout.close ();
				Inputstream.close ();
		} this.zipFile.close ();
		catch (IOException IoE) {ioe.printstacktrace (); }/** * Extract the specified zip file.
	where "GB18030" to solve the Chinese garbled * * @param unzipfilename * Need to extract ZIP file name * @param outputpath * Output Path * *
		public void UnZip (String unzipfilename,string outputpath) {FileOutputStream fileout;
		File file;

		InputStream InputStream;

			try {this.zipfile = new ZipFile (unzipfilename, "GB18030"); For (Enumeration entries = This.zipFile.getEntries (); entries. hasMoreElements ();)
				{ZipEntry entry = (zipentry) entries.nextelement ();

				File = new file (Outputpath+entry.getname ()); if (enTry.isdirectory ()) {//is a directory, the File.mkdirs () is created;
					else {//is a file//if the parent directory of the specified file does not exist, it is created.
					File parent = File.getparentfile ();
					if (parent!= null &&!parent.exists ()) {parent.mkdirs ());

					} InputStream = Zipfile.getinputstream (entry);
					Fileout = new FileOutputStream (file);
					while ((This.readedbytes = Inputstream.read (this.buf)) > 0) {fileout.write (this.buf, 0, this.readedbytes);

					} fileout.close ();
				Inputstream.close ();
		} this.zipFile.close ();
		catch (IOException IoE) {ioe.printstacktrace (); /** * Add File.separator * to file path or directory end * @param fileName * You need to add a path delimiter path * @return If the path already has a delimiter, it is returned as is.
	 Otherwise, the separator is added and then returned.
		* * Private string Appendseparator (string path) {if (!path.endswith (file.separator)) path = = File.separator;
	return path;
	 /** * Extract the specified zip file. * * @param unzipfile * Need to extract the zip file object/public void UnZip (file unzipfile) {UnZip (unzipfile.tostring ());
	 /** * Sets the buffer size for compression or decompression.
	* * @param bufsize * Buffer size */public void setbufsize (int bufsize) {this.bufsize = bufsize; }//main function, for testing antzip class * * public static void Main (string[] args) throws exception{* if (args.length>=2) {Antzip Zi
	 p = new Antzip (); * * IF (args[0].equals ("-zip")) {//Convert all subsequent parameters to File object file[] files = new file[* args.length-1]; for (int i = 0;i < Args.length-1;
	 i++) {files = new * File (args[i + 1]);
	 * *///Zip.dozip The first file name as Zip filename (files, files[0].getname ()); * * return;
	 else if (args[0].equals ("-unzip")) {Zip.unzip (args[1]);
	 * * SYSTEM.OUT.PRINTLN ("Usage:"); * SYSTEM.OUT.PRINTLN ("compression: Java Antzip-zip [DirectoryName | FileName] ...
	 "); * SYSTEM.OUT.PRINTLN ("decompression: Java antzip-unzip filename.zip"); }
	 */

}

The second is to start by modifying the Zipinputstream and Zipoutputstream coding for the filename. We can modify the original code of Zipinputstream and Zipoutputstream from JDK's src.zip:
First, Zipoutputstream.java
1. Obtain the Zipoutputstream.java source code from the JDK's src.zip, save the new file to c:/java/util/zip this folder and change the file name to Czipoutputstream.java.
2. Start modifying the original code, change the class name to Czipoutputstream
3. The constructor must also be changed to Czipoutputstream
4. Add Member, this member record encoding method
Private String encoding= "UTF-8";
5. Add a new constructor (this constructor allows the class to encode the filename at new time)
Public Czipoutputstream (OutputStream out,string encoding) { 
     super (out, new Deflater (deflater.default_compression , true)); 
     Usesdefaultdeflater = true; 
     this.encoding=encoding; 
  

6. Find byte[] namebytes = getutf8bytes (e.name);(there are two places), modify it as follows:
byte[] namebytes = null; 
  Try 
  { 
    if (this.encoding.toUpperCase (). Equals ("UTF-8")) 
       namebytes =getutf8bytes (e.name); 
    else 
       namebytes= e.name.getbytes (this.encoding); 
  } 
  catch (Exception bytee) 
  { 
    namebytes=getutf8bytes (e.name); 
  

7. Store the file in the C:/java/util/zip folder, please remember to have this path structure,
To put Czipoutputstream.class in the correct package structure.


Second, Zipinputstream.java
1. Obtain the Zipinputstream.java source code from the JDK's src.zip, save the new file to c:/java/util/zip this folder and change the file name to Czipinputstream.java.
2. Start modifying the original code, change the class name to Czipinputstream
3. The constructor must also be changed to Czipinputstream
4. Add Member, this member record encoding method
Private String encoding= "UTF-8";
5. Add a new constructor as follows (this constructor allows the class to encode the filename at new time)
Public Czipinputstream (InputStream in,string encoding) { 
  super (new Pushbackinputstream (in,512), New Inflater (True ); 
  Usesdefaultinflater = true; 
  if (in = = null) { 
       throw new NullPointerException ("is null"); 
  } 
  this.encoding=encoding; 


6. Find ZipEntry e = Createzipentry (getutf8string (b, 0, Len)); This line, change it to the following:
ZipEntry E=null; 
Try 
{ 
  if (this.encoding.toUpperCase (). Equals ("UTF-8")) 
     E=createzipentry (getutf8string (b, 0, Len)); 
  else 
     e=createzipentry (new String (b,0,len,this.encoding)); 
catch (Exception bytee) 
{ 
  e=createzipentry (getutf8string (b, 0, Len)); 


7. Store the file in C:/java/util/zip this folder, please remember to have this path structure, in order to put Czipinputstream.class in the correct package structure


After the above two files are stored compile produce czipoutputstream.class and czipinputstream.class, use WinZip to open [java_home]/jre/lib/ Rt.jar This file, add Czipoutputstream.class and Czipinputstream.class, remember "save full path info" must tick.
Then, when compressing and decompressing the problem of Chinese file name and path, we can specify the encoding method to deal with.
Czipoutputstream zos=new Czipoutputstream (outputstream os,string encoding);

Czipinputstream zins=new Czipinputstream (inputstream ins,string encoding);
Take "Compression and decompression (1)" For example:
FileOutputStream Fos =new FileOutputStream (Request.getrealpath ("/") + "Myzip.zip");

Czipoutputstream zos=new czipoutputstream (FOS, "GBK");

Other places do not have to change, you can handle the compression of the document name.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.