- 浏览: 1007732 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (394)
- OSGI (14)
- 多线程 (10)
- 数据库 (30)
- J2ME (1)
- JAVA基础知识 (46)
- 引用包 (1)
- 设计模式 (7)
- 工作流 (2)
- Ubuntu (7)
- 搜索引擎 (6)
- QT (2)
- Ubuntu下编程 (1)
- 小程序 (2)
- UML (1)
- Servlet (10)
- spring (16)
- IM (12)
- 文档视频转为flash格式在线播放 (19)
- Maven (8)
- 远程调用 (2)
- PHPRPC (1)
- EXTJS学习 (2)
- Hibernate (16)
- 技术文章 (38)
- flex (5)
- 海量数据处理 (5)
- FTP (8)
- JS (10)
- Struts (1)
- hibernate search (13)
- JQuery (2)
- EMail (3)
- 算法 (4)
- SVN (7)
- JFreeChart (4)
- 面试 (4)
- 正规表达式 (2)
- 数据库性能优化 (10)
- JVM (6)
- Http Session Cookie (7)
- 网络 (12)
- Hadoop (2)
- 性能 (1)
最新评论
-
hy1235366:
能够随便也发一下,你退火算法程序使用的DistanceMatr ...
模拟退火算法总结(含例子)(转) -
梅强强:
感谢分享。。帮大忙了
swftools转换文件时线程堵塞问题的解决方法 -
wenlongsust:
openoffice和文件不在同一个服务器上,用过吗?
[JODConverter]word转pdf心得分享(转) -
2047699523:
如何在java Web项目中开发WebService接口htt ...
利用Java编写简单的WebService实例 -
abingpow:
唉,看起来好像很详细很不错的样子,可惜不是篇面向初学者的文章, ...
Spring与OSGi的整合(二)(转)
今天有同学问起来用java做压缩和解压缩的程序时,出现中文问题,我以前做过,不过已经很久了,那里又没有写日志,所以也忘记了自己所做的压缩小程序,今天又重新写一编,真是很浪费时间,平时要多做笔记,以后用到时就可以顺手拿来,不然跟白学一样,一切从头再来,切记切记。
这里是用java.util.zip.ZipOutputStream来做压缩的话会出现将中文名字的文件一缩后,在压缩包里就会出现乱码的文件名,解决的办法可以修改java.util.zip.ZipOutputStream这个类,加入编码方式就可以,具体如下:
my.java.util.zip.ZipOutputStream
同时也要修改java.util.zip.ZipEntry这个类,主要是增加了三个属性:
int flag;
int version;
long offset;
在修改的ZipOutputStream类里会用到,具体ZipEntry代码如下:
my.java.util.zip.ZipEntry
有了上面那两个类后,我们就不用java.util.zip包下的这两个类来做压缩,而是用来面的修改后的类来做,我写了一个简单的测试程序如下:
解压程序我也写了,如下:
我以为用修改后的my.java.util.zip.ZipOutputStream或my.java.util.zip.ZipInputStream就可以解决问题,我将这两个类拷给同学,在他那里会出错,原来这两个类修改也包括了对它们引用到的类的修改,我现将它们打包发上来,导入就可以用了,中文名的压缩和解压缩的问题也可以解决了。
这里是用java.util.zip.ZipOutputStream来做压缩的话会出现将中文名字的文件一缩后,在压缩包里就会出现乱码的文件名,解决的办法可以修改java.util.zip.ZipOutputStream这个类,加入编码方式就可以,具体如下:
my.java.util.zip.ZipOutputStream
/* * * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package my.java.util.zip; import java.io.IOException; import java.io.OutputStream; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import java.util.zip.CRC32; import java.util.zip.Deflater; import java.util.zip.ZipException; public class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { private ZipEntry entry; private Vector entries = new Vector(); private Hashtable names = new Hashtable(); private CRC32 crc = new CRC32(); private long written; private long locoff = 0; private String comment; private int method = DEFLATED; private boolean finished; private String encoding = "UTF-8"; // 为了支持中文,添加 private boolean closed = false; /** * Check to make sure that this stream has not been closed */ private void ensureOpen() throws IOException { if (closed) { throw new IOException("Stream closed"); } } /** * Compression method for uncompressed (STORED) entries. */ public static final int STORED = ZipEntry.STORED; /** * Compression method for compressed (DEFLATED) entries. */ public static final int DEFLATED = ZipEntry.DEFLATED; /** * Creates a new ZIP output stream. * * @param out * the actual output stream */ public ZipOutputStream(OutputStream out) { super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true)); usesDefaultDeflater = true; } /** * Creates a new ZIP output stream. * * @param out * the actual output stream * @param encoding * set stream's code 为了支持中文添加 */ public ZipOutputStream(OutputStream out, String encoding) { super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true)); usesDefaultDeflater = true; this.encoding = encoding; } /** * Sets the ZIP file comment. * * @param comment * the comment string * @exception IllegalArgumentException * if the length of the specified ZIP file comment is greater * than 0xFFFF bytes */ public void setComment(String comment) { if (comment != null && comment.length() > 0xffff / 3 && getUTF8Length(comment) > 0xffff) { throw new IllegalArgumentException("ZIP file comment too long."); } this.comment = comment; } /** * Sets the default compression method for subsequent entries. This default * will be used whenever the compression method is not specified for an * individual ZIP file entry, and is initially set to DEFLATED. * * @param method * the default compression method * @exception IllegalArgumentException * if the specified compression method is invalid */ public void setMethod(int method) { if (method != DEFLATED && method != STORED) { throw new IllegalArgumentException("invalid compression method"); } this.method = method; } /** * Sets the compression level for subsequent entries which are DEFLATED. The * default setting is DEFAULT_COMPRESSION. * * @param level * the compression level (0-9) * @exception IllegalArgumentException * if the compression level is invalid */ public void setLevel(int level) { def.setLevel(level); } /** * Begins writing a new ZIP file entry and positions the stream to the start * of the entry data. Closes the current entry if still active. The default * compression method will be used if no compression method was specified * for the entry, and the current time will be used if the entry has no set * modification time. * * @param e * the ZIP entry to be written * @exception ZipException * if a ZIP format error has occurred * @exception IOException * if an I/O error has occurred */ public void putNextEntry(ZipEntry e) throws IOException { ensureOpen(); if (entry != null) { closeEntry(); // close previous entry } if (e.time == -1) { e.setTime(System.currentTimeMillis()); } if (e.method == -1) { e.method = method; // use default method } switch (e.method) { case DEFLATED: if (e.size == -1 || e.csize == -1 || e.crc == -1) { // store size, compressed size, and crc-32 in data descriptor // immediately following the compressed entry data e.flag = 8; } else if (e.size != -1 && e.csize != -1 && e.crc != -1) { // store size, compressed size, and crc-32 in LOC header e.flag = 0; } else { throw new ZipException( "DEFLATED entry missing size, compressed size, or crc-32"); } e.version = 20; break; case STORED: // compressed size, uncompressed size, and crc-32 must all be // set for entries using STORED compression method if (e.size == -1) { e.size = e.csize; } else if (e.csize == -1) { e.csize = e.size; } else if (e.size != e.csize) { throw new ZipException( "STORED entry where compressed != uncompressed size"); } if (e.size == -1 || e.crc == -1) { throw new ZipException( "STORED entry missing size, compressed size, or crc-32"); } e.version = 10; e.flag = 0; break; default: throw new ZipException("unsupported compression method"); } e.offset = written; if (names.put(e.name, e) != null) { throw new ZipException("duplicate entry: " + e.name); } writeLOC(e); entries.addElement(e); entry = e; } /** * Closes the current ZIP entry and positions the stream for writing the * next entry. * * @exception ZipException * if a ZIP format error has occurred * @exception IOException * if an I/O error has occurred */ public void closeEntry() throws IOException { ensureOpen(); ZipEntry e = entry; if (e != null) { switch (e.method) { case DEFLATED: def.finish(); while (!def.finished()) { deflate();// defate意思:漏气; (使)…瘪下去 } if ((e.flag & 8) == 0) { // verify size, compressed size, and crc-32 settings if (e.size != def.getTotalIn()) { throw new ZipException("invalid entry size (expected " + e.size + " but got " + def.getTotalIn() + " bytes)"); } if (e.csize != def.getTotalOut()) { throw new ZipException( "invalid entry compressed size (expected " + e.csize + " but got " + def.getTotalOut() + " bytes)"); } if (e.crc != crc.getValue()) { throw new ZipException( "invalid entry CRC-32 (expected 0x" + Long.toHexString(e.crc) + " but got 0x" + Long.toHexString(crc.getValue()) + ")"); } } else { e.size = def.getTotalIn(); e.csize = def.getTotalOut(); e.crc = crc.getValue(); writeEXT(e); } def.reset(); written += e.csize; break; case STORED: // we already know that both e.size and e.csize are the same if (e.size != written - locoff) { throw new ZipException("invalid entry size (expected " + e.size + " but got " + (written - locoff) + " bytes)"); } if (e.crc != crc.getValue()) { throw new ZipException("invalid entry crc-32 (expected 0x" + Long.toHexString(e.crc) + " but got 0x" + Long.toHexString(crc.getValue()) + ")"); } break; default: throw new InternalError("invalid compression method"); } crc.reset(); entry = null; } } /** * Writes an array of bytes to the current ZIP entry data. This method will * block until all the bytes are written. * * @param b * the data to be written * @param off * the start offset in the data * @param len * the number of bytes that are written * @exception ZipException * if a ZIP file error has occurred * @exception IOException * if an I/O error has occurred */ public synchronized void write(byte[] b, int off, int len)throws IOException { ensureOpen(); if (off < 0 || len < 0 || off > b.length - len) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } if (entry == null) { throw new ZipException("no current ZIP entry"); } switch (entry.method) { case DEFLATED: super.write(b, off, len); break; case STORED: written += len; if (written - locoff > entry.size) { throw new ZipException( "attempt to write past end of STORED entry"); } out.write(b, off, len); break; default: throw new InternalError("invalid compression method"); } crc.update(b, off, len); } /** * Finishes writing the contents of the ZIP output stream without closing * the underlying stream. Use this method when applying multiple filters in * succession to the same output stream. * * @exception ZipException * if a ZIP file error has occurred * @exception IOException * if an I/O exception has occurred */ public void finish() throws IOException { ensureOpen(); if (finished) { return; } if (entry != null) { closeEntry(); } if (entries.size() < 1) { throw new ZipException("ZIP file must have at least one entry"); } // write central directory long off = written; Enumeration e = entries.elements(); while (e.hasMoreElements()) { writeCEN((ZipEntry) e.nextElement()); } writeEND(off, written - off); finished = true; } /** * Closes the ZIP output stream as well as the stream being filtered. * * @exception ZipException * if a ZIP file error has occurred * @exception IOException * if an I/O error has occurred */ public void close() throws IOException { if (!closed) { super.close(); closed = true; } } /* * Writes local file (LOC) header for specified entry. */ private void writeLOC(ZipEntry e) throws IOException { writeInt(LOCSIG); // LOC header signature writeShort(e.version); // version needed to extract writeShort(e.flag); // general purpose bit flag writeShort(e.method); // compression method writeInt(e.time); // last modification time if ((e.flag & 8) == 8) { // store size, uncompressed size, and crc-32 in data descriptor // immediately following compressed entry data writeInt(0); writeInt(0); writeInt(0); } else { writeInt(e.crc); // crc-32 writeInt(e.csize); // compressed size writeInt(e.size); // uncompressed size } // 为了支持中文,注释 // byte[] nameBytes = getUTF8Bytes(e.name); // 为了支持中文,添加 begin 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); } // 为了支持中文,添加 end writeShort(nameBytes.length); writeShort(e.extra != null ? e.extra.length : 0); writeBytes(nameBytes, 0, nameBytes.length); if (e.extra != null) { writeBytes(e.extra, 0, e.extra.length); } locoff = written; } /* * Writes extra data descriptor (EXT) for specified entry. */ private void writeEXT(ZipEntry e) throws IOException { writeInt(EXTSIG); // EXT header signature writeInt(e.crc); // crc-32 writeInt(e.csize); // compressed size writeInt(e.size); // uncompressed size } /* * Write central directory (CEN) header for specified entry. REMIND: add * support for file attributes */ private void writeCEN(ZipEntry e) throws IOException { writeInt(CENSIG); // CEN header signature writeShort(e.version); // version made by writeShort(e.version); // version needed to extract writeShort(e.flag); // general purpose bit flag writeShort(e.method); // compression method writeInt(e.time); // last modification time writeInt(e.crc); // crc-32 writeInt(e.csize); // compressed size writeInt(e.size); // uncompressed size // 为了支持中文,注释 // byte[] nameBytes = getUTF8Bytes(e.name); // 为了支持中文,添加 begin 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); } // 为了支持中文,添加 end writeShort(nameBytes.length); writeShort(e.extra != null ? e.extra.length : 0); byte[] commentBytes; if (e.comment != null) { commentBytes = getUTF8Bytes(e.comment); writeShort(commentBytes.length); } else { commentBytes = null; writeShort(0); } writeShort(0); // starting disk number writeShort(0); // internal file attributes (unused) writeInt(0); // external file attributes (unused) writeInt(e.offset); // relative offset of local header writeBytes(nameBytes, 0, nameBytes.length); if (e.extra != null) { writeBytes(e.extra, 0, e.extra.length); } if (commentBytes != null) { writeBytes(commentBytes, 0, commentBytes.length); } } /* * Writes end of central directory (END) header. */ private void writeEND(long off, long len) throws IOException { writeInt(ENDSIG); // END record signature writeShort(0); // number of this disk writeShort(0); // central directory start disk writeShort(entries.size()); // number of directory entries on disk writeShort(entries.size()); // total number of directory entries writeInt(len); // length of central directory writeInt(off); // offset of central directory if (comment != null) { // zip file comment byte[] b = getUTF8Bytes(comment); writeShort(b.length); writeBytes(b, 0, b.length); } else { writeShort(0); } } /* * Writes a 16-bit short to the output stream in little-endian byte order. */ private void writeShort(int v) throws IOException { OutputStream out = this.out; out.write((v >>> 0) & 0xff); out.write((v >>> 8) & 0xff); written += 2; } /* * Writes a 32-bit int to the output stream in little-endian byte order. */ private void writeInt(long v) throws IOException { OutputStream out = this.out; out.write((int) ((v >>> 0) & 0xff)); out.write((int) ((v >>> 8) & 0xff)); out.write((int) ((v >>> 16) & 0xff)); out.write((int) ((v >>> 24) & 0xff)); written += 4; } /* * Writes an array of bytes to the output stream. */ private void writeBytes(byte[] b, int off, int len) throws IOException { super.out.write(b, off, len); written += len; } /* * Returns the length of String's UTF8 encoding. */ static int getUTF8Length(String s) { int count = 0; for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (ch <= 0x7f) { count++; } else if (ch <= 0x7ff) { count += 2; } else { count += 3; } } return count; } /* * Returns an array of bytes representing the UTF8 encoding of the specified * String. */ private static byte[] getUTF8Bytes(String s) { char[] c = s.toCharArray(); int len = c.length; // Count the number of encoded bytes... int count = 0; for (int i = 0; i < len; i++) { int ch = c[i]; if (ch <= 0x7f) { count++; } else if (ch <= 0x7ff) { count += 2; } else { count += 3; } } // Now return the encoded bytes... byte[] b = new byte[count]; int off = 0; for (int i = 0; i < len; i++) { int ch = c[i]; if (ch <= 0x7f) { b[off++] = (byte) ch; } else if (ch <= 0x7ff) { b[off++] = (byte) ((ch >> 6) | 0xc0); b[off++] = (byte) ((ch & 0x3f) | 0x80); } else { b[off++] = (byte) ((ch >> 12) | 0xe0); b[off++] = (byte) (((ch >> 6) & 0x3f) | 0x80); b[off++] = (byte) ((ch & 0x3f) | 0x80); } } return b; } }
同时也要修改java.util.zip.ZipEntry这个类,主要是增加了三个属性:
int flag;
int version;
long offset;
在修改的ZipOutputStream类里会用到,具体ZipEntry代码如下:
my.java.util.zip.ZipEntry
/* * * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package my.java.util.zip; import java.util.Date; public class ZipEntry implements ZipConstants, Cloneable { String name; // entry name long time = -1; // modification time (in DOS time) long crc = -1; // crc-32 of entry data long size = -1; // uncompressed size of entry data long csize = -1; // compressed size of entry data int method = -1; // compression method byte[] extra; // optional extra field data for entry String comment; // optional comment string for entry // The following flags are used only by Zip{Input,Output}Stream int flag; // bit flags int version; // version needed to extract long offset; // offset of loc header /** * Compression method for uncompressed entries. */ public static final int STORED = 0; /** * Compression method for compressed (deflated) entries. */ public static final int DEFLATED = 8; // static { // /* load the zip library */ // java.security.AccessController.doPrivileged( // new sun.security.action.LoadLibraryAction("zip")); // //initIDs(); // } private static native void initIDs(); /** * Creates a new zip entry with the specified name. * * @param name * the entry name * @exception NullPointerException * if the entry name is null * @exception IllegalArgumentException * if the entry name is longer than 0xFFFF bytes */ public ZipEntry(String name) { if (name == null) { throw new NullPointerException(); } if (name.length() > 0xFFFF) { throw new IllegalArgumentException("entry name too long"); } this.name = name; } /** * Creates a new zip entry with fields taken from the specified zip entry. * * @param e * a zip Entry object */ /** * Returns the name of the entry. * * @return the name of the entry */ public String getName() { return name; } /** * Sets the modification time of the entry. * * @param time * the entry modification time in number of milliseconds since * the epoch * @see #getTime() */ public void setTime(long time) { this.time = javaToDosTime(time); } /** * Returns the modification time of the entry, or -1 if not specified. * * @return the modification time of the entry, or -1 if not specified * @see #setTime(long) */ public long getTime() { return time != -1 ? dosToJavaTime(time) : -1; } /** * Sets the uncompressed size of the entry data. * * @param size * the uncompressed size in bytes * @exception IllegalArgumentException * if the specified size is less than 0 or greater than * 0xFFFFFFFF bytes * @see #getSize() */ public void setSize(long size) { if (size < 0 || size > 0xFFFFFFFFL) { throw new IllegalArgumentException("invalid entry size"); } this.size = size; } /** * Returns the uncompressed size of the entry data, or -1 if not known. * * @return the uncompressed size of the entry data, or -1 if not known * @see #setSize(long) */ public long getSize() { return size; } /** * Returns the size of the compressed entry data, or -1 if not known. In the * case of a stored entry, the compressed size will be the same as the * uncompressed size of the entry. * * @return the size of the compressed entry data, or -1 if not known * @see #setCompressedSize(long) */ public long getCompressedSize() { return csize; } /** * Sets the size of the compressed entry data. * * @param csize * the compressed size to set to * @see #getCompressedSize() */ public void setCompressedSize(long csize) { this.csize = csize; } /** * Sets the CRC-32 checksum of the uncompressed entry data. * * @param crc * the CRC-32 value * @exception IllegalArgumentException * if the specified CRC-32 value is less than 0 or greater * than 0xFFFFFFFF * @see #setCrc(long) */ public void setCrc(long crc) { if (crc < 0 || crc > 0xFFFFFFFFL) { throw new IllegalArgumentException("invalid entry crc-32"); } this.crc = crc; } /** * Returns the CRC-32 checksum of the uncompressed entry data, or -1 if not * known. * * @return the CRC-32 checksum of the uncompressed entry data, or -1 if not * known * @see #getCrc() */ public long getCrc() { return crc; } /** * Sets the compression method for the entry. * * @param method * the compression method, either STORED or DEFLATED * @exception IllegalArgumentException * if the specified compression method is invalid * @see #getMethod() */ public void setMethod(int method) { if (method != STORED && method != DEFLATED) { throw new IllegalArgumentException("invalid compression method"); } this.method = method; } /** * Returns the compression method of the entry, or -1 if not specified. * * @return the compression method of the entry, or -1 if not specified * @see #setMethod(int) */ public int getMethod() { return method; } /** * Sets the optional extra field data for the entry. * * @param extra * the extra field data bytes * @exception IllegalArgumentException * if the length of the specified extra field data is greater * than 0xFFFF bytes * @see #getExtra() */ public void setExtra(byte[] extra) { if (extra != null && extra.length > 0xFFFF) { throw new IllegalArgumentException("invalid extra field length"); } this.extra = extra; } /** * Returns the extra field data for the entry, or null if none. * * @return the extra field data for the entry, or null if none * @see #setExtra(byte[]) */ public byte[] getExtra() { return extra; } /** * Sets the optional comment string for the entry. * * @param comment * the comment string * @exception IllegalArgumentException * if the length of the specified comment string is greater * than 0xFFFF bytes * @see #getComment() */ public void setComment(String comment) { if (comment != null && comment.length() > 0xffff / 3 && ZipOutputStream.getUTF8Length(comment) > 0xffff) { throw new IllegalArgumentException("invalid entry comment length"); } this.comment = comment; } /** * Returns the comment string for the entry, or null if none. * * @return the comment string for the entry, or null if none * @see #setComment(String) */ public String getComment() { return comment; } /** * Returns true if this is a directory entry. A directory entry is defined * to be one whose name ends with a '/'. * * @return true if this is a directory entry */ public boolean isDirectory() { return name.endsWith("/"); } /** * Returns a string representation of the ZIP entry. */ public String toString() { return getName(); } /* * Converts DOS time to Java time (number of milliseconds since epoch). */ private static long dosToJavaTime(long dtime) { Date d = new Date((int) (((dtime >> 25) & 0x7f) + 80), (int) (((dtime >> 21) & 0x0f) - 1), (int) ((dtime >> 16) & 0x1f), (int) ((dtime >> 11) & 0x1f), (int) ((dtime >> 5) & 0x3f), (int) ((dtime << 1) & 0x3e)); return d.getTime(); } /* * Converts Java time to DOS time. */ private static long javaToDosTime(long time) { Date d = new Date(time); int year = d.getYear() + 1900; if (year < 1980) { return (1 << 21) | (1 << 16); } return (year - 1980) << 25 | (d.getMonth() + 1) << 21 | d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 | d.getSeconds() >> 1; } /** * Returns the hash code value for this entry. */ public int hashCode() { return name.hashCode(); } /** * Returns a copy of this entry. */ public Object clone() { try { ZipEntry e = (ZipEntry) super.clone(); e.extra = (extra == null ? null : (byte[]) extra.clone()); return e; } catch (CloneNotSupportedException e) { // This should never happen, since we are Cloneable throw new InternalError(); } } }
有了上面那两个类后,我们就不用java.util.zip包下的这两个类来做压缩,而是用来面的修改后的类来做,我写了一个简单的测试程序如下:
package test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import my.java.util.zip.ZipEntry; import my.java.util.zip.ZipOutputStream; public class zip { private ZipOutputStream zipOutputStream; private FileOutputStream fos = null; public zip(File in , File out) { try { fos = new FileOutputStream(out); } catch (FileNotFoundException e) { e.printStackTrace(); } zipOutputStream = new ZipOutputStream(fos,"GBK");//只能是GBK,用UTF-8不行 doZip(in, zipOutputStream, null); closeZipOutputStream(); } /** * 用递归调用的方式将一个文件夹下的所有文件压缩进压缩包里 * @param input 输入要压缩的文件的路径 * @param zos 压缩输出流 * @param relativePath 文件或文件夹在压缩包里的相对路径,一开始应将相对路径设置为null */ public void doZip(File input , ZipOutputStream zos , String relativePath) { FileInputStream fis; byte[] b = new byte[1024]; try { if(input.isDirectory()) { relativePath = relativePath == null ? input.getName() : relativePath + "/" + input.getName(); zos.putNextEntry(new ZipEntry(relativePath + "/"));//ZipEntry应该是用来设置压缩文件所存放的相对路径的,当是文件夹时一定要后面加上"/",是文件则不用加 File[] fileList = input.listFiles(); for(int i = 0 ; i < fileList.length ; i++) { if(fileList[i].isDirectory()) { doZip(fileList[i] , zos , relativePath); } else { zos.putNextEntry(new ZipEntry(relativePath + "/" + fileList[i].getName()));//这个一定不要忘记了,不然文件是压缩不进入的哦 fis = new FileInputStream(fileList[i]); while(fis.read(b) != -1) { zos.write(b); } fis.close(); } } } else { relativePath = relativePath == null ? input.getName() : relativePath + "/" + input.getName(); zos.putNextEntry(new ZipEntry(relativePath));//文件不用加上"/" fis = new FileInputStream(input); while(fis.read(b) != -1) { zos.write(b); } fis.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); } } //关闭输出流 public void closeZipOutputStream() { try { zipOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } //简单测试 public static void main(String[] args) { zip test = new zip(new File("F:\\MQ") , new File("F:/MQ.zip")); System.out.println("压缩完成"); } }
解压程序我也写了,如下:
package test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipException; import java.util.zip.ZipFile; import my.java.util.zip.ZipEntry; import my.java.util.zip.ZipInputStream; //解压简单例子 public class unZip { File in; File out; private ZipInputStream zis; public unZip(File in , File out) { this.in = in; this.out = out; initial(); } public void initial() { //下面是用来检查输入的文件是否是zip文件类型用的,若输入的是.rar类型也会报异常 try { ZipFile zipFile = new ZipFile(in); zipFile.close(); } catch (ZipException e1) { e1.printStackTrace(); return ; } catch (IOException e1) { e1.printStackTrace(); return ; } if(out == null || !out.isDirectory()) { System.out.println("请选择正确的解压存放的目录!"); return ; } try { zis = new ZipInputStream(new FileInputStream(in),"GBK");//支持中文的地方 doUnZip(); } catch (FileNotFoundException e) { e.printStackTrace(); return ; } } public void doUnZip() { String pathName; ZipEntry zipEntry; File output; FileOutputStream fos; byte[] b; int len; String desPath;//存放的目标路径 String tempPath; desPath = out.getAbsolutePath(); try { zipEntry = zis.getNextEntry();//用它可以遍历在压缩包里的所有条目(包括文件和文件夹都会识别出来) while(zipEntry != null) { System.out.println(zipEntry.getName()); tempPath = zipEntry.getName(); //这里的文件路径用"\\"和"/"混合也是可以正确的创建目录或访问目录等,还是比较方便的 if(desPath.endsWith("\\") || desPath.endsWith("/")) tempPath = desPath + tempPath; else tempPath = desPath + File.separator + tempPath; output = new File(tempPath); if(zipEntry.isDirectory())//这里注意啦,不是output.isDirectory()来判断,是用ZipEntry来判断 { /* * File类的mkdir()和mkdirs()区别 * 简单来说,mkdir()就是创建一个目录,但前提是要创建的目录的父目录一定要存在。 例如:要创建D:\myeclipseprg7\CompilerTest\WebRoot\works 这个目录,那么D:\myeclipseprg7\CompilerTest\WebRoot\这个目录就一定要存在,否则用mkdir()无法成功创建目录。如果父目录不存在,我们可以用mkdirs(),这样不管父目录是否存在,都能创建成功。这样看来,似乎mkdir()这个函数没多大用处,今后建议大家只使用mkdirs()。 */ output.mkdirs(); } else//对于文件就直接输出 { fos = new FileOutputStream(output); b = new byte[1024]; while( (len = zis.read(b)) != -1) { fos.write(b, 0, len); } fos.close(); } zipEntry = zis.getNextEntry();//下一条条目 } } catch (IOException e) { e.printStackTrace(); return; } closeZipInputStream(); } public void closeZipInputStream() { try { zis.close(); } catch (IOException e) { e.printStackTrace(); return ; } } public static void main(String[] args) { unZip test = new unZip(new File("F:\\chenwenbiao.zip"), new File("F:\\")); } }
我以为用修改后的my.java.util.zip.ZipOutputStream或my.java.util.zip.ZipInputStream就可以解决问题,我将这两个类拷给同学,在他那里会出错,原来这两个类修改也包括了对它们引用到的类的修改,我现将它们打包发上来,导入就可以用了,中文名的压缩和解压缩的问题也可以解决了。
- 压缩包中文问题.rar (17 KB)
- 下载次数: 191
相关推荐
zipEntry.setComment("压缩文件"); // 可以添加注释,同样需要指定字符集 zos.putNextEntry(zipEntry); try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) { byte[] buffer...
java批量压缩文件跟文件夹,目前还不支持中文名,后期会改进,谢谢
解决java压缩zip文件时的中文乱码问题 ...实现:java压缩文件成zip实现无乱码。 包括:写好的工具类与jar包。 使用方法:导入ant.jar包,调用CompressExcelOperate中的方法,即可实现压缩文件,并保证没有中文乱码。
然而,当压缩文件包含中文字符时,解压缩过程中可能会遇到乱码问题。这是因为编码格式不匹配或者处理方式不当导致的。本篇文章将深入探讨如何在Android平台上解决Java ZIP库在解压缩中文文件时出现的乱码问题。 ...
java 压缩目录中的所有文件 中文文件名不会乱码
2、指定文件夹(文件夹中必须有一个文件),程序会自动的压缩文件为 zip,然后下载删除源文件与压缩文件。 3、可以指定文件都为最后生成为zip文件下载,且删除源文件。 1、压缩文件或者目录(只是压缩不删除):...
### Java压缩文件代码详解 #### 一、概述 在日常的软件开发过程中,对文件进行压缩处理是一项常见的需求。无论是为了节省存储空间还是提高传输效率,掌握如何使用Java语言进行文件压缩都是非常重要的技能之一。本...
时间紧迫,暂时存在中文文件夹名称乱码问题 不影响文件夹内各类型文件内容 实现方法见功能说明txt文档,只需传入文件夹路径,Zip文件路径,密码 本人JAVA实习生,因业务需求研究此方法,代码质量不高,只为了实现...
"truezip6.6"是一个专门针对这些问题的Java库,它为开发者提供了强大的文件系统接口,使得在Java中操作压缩文件变得更加便捷和可靠。 TrueZip库的核心功能在于提供了一个与Java标准文件系统API兼容的接口,这意味着...
时间紧迫,暂时存在中文文件夹名称乱码问题 不影响文件夹内各类型文件内容 实现方法见功能说明txt文档,只需传入文件夹路径,Zip文件路径,密码 本人JAVA实习生,因业务需求研究此方法,代码质量不高,只为了...
Apache Commons Compress库是Java中一个强大的工具,它提供了对多种压缩格式的支持,包括zip,而且能够处理中文文件名的问题,避免了因为字符编码不正确导致的乱码问题。 首先,我们要了解Java内置的`java.util.zip...
java解压缩文件支持中文,经过测试,可执行,项目中正在应用
在Java编程中,处理压缩和解压缩ZIP文件是一项常见的任务,尤其当文件中包含中文字符时,可能会遇到中文乱码的问题。这是因为Java的标准库在处理非ASCII编码时可能存在不足。本篇文章将详细介绍如何使用Java标准库...
JAVA操作压缩文件的包。JAVA操作压缩文件的包。JAVA操作压缩文件的包。JAVA操作压缩文件的包。
解决 Java 压缩文件乱码问题可以通过使用 Apache 的开源类库 ZipOutputStream 和 ZipEntry,设置编码方式为 gbk,使用 setEncoding 方法设置压缩文件的注释编码方式为 gbk,从而解决中文乱码问题。
本篇文章将详细讲解如何使用Java来解压缩ZIP格式的压缩文件,特别是那些包含中文文件名的压缩包。我们将探讨相关API的使用,以及解决中文文件名在解压过程中可能出现的问题。 1. **Java的压缩与解压缩库**: Java...
在Java编程中,向现有的ZIP压缩包追加文件通常需要经过解压、修改、再压缩的步骤,因为标准的Java ZIP库(如`java.util.zip`包)并不直接支持追加到已存在的ZIP文件。本篇文章将深入探讨如何实现这个功能,主要关注...