java解压缩zip文件时文件内中文部分乱码

xaqk008 2012-04-11 04:56:31
RT 网上说用org.apache.tools.zip可以解决,我用后没有效果(注释掉的部分)。代码如下,求指教

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import java.util.zip.ZipEntry;
import java.util.Enumeration;
import java.util.zip.ZipInputStream;


import de.innosystec.unrar.Archive;
import de.innosystec.unrar.rarfile.FileHeader;

//import org.apache.tools.zip.ZipEntry;
//import org.apache.tools.zip.ZipFile;
//import org.apache.tools.zip.ZipOutputStream;




public class UnRarUtil
{
private static void unRar(String srcRar,String destDir) throws Exception
{
Archive a =null;
FileOutputStream fos = null;
try{
a = new Archive(new File(srcRar));
FileHeader fh = a.nextFileHeader();
while(fh != null)
{
if(!fh.isDirectory())
{
//根据不同的操作系统取得相应的destFileName,destDirNamme
String compressFileName = fh.getFileNameString().trim();
String destFileName = "";
String destDirNamme = "";
//非windows操作系统
if(File.separator.equals("/"))
{
destFileName = destDir + compressFileName.replaceAll("\\\\", "/");
destDirNamme = destFileName.substring(0, destFileName.lastIndexOf("/"));
}
else//windows系统
{
destFileName = destDir + compressFileName.replaceAll("/", "\\\\");
destDirNamme = destFileName.substring(0, destFileName.lastIndexOf("\\"));
}

File dir = new File(destDirNamme);
if(!dir.exists() || !dir.isDirectory())
{
dir.mkdirs();
}

fos = new FileOutputStream(new File(destFileName));
a.extractFile(fh, fos);
fos.close();
fos = null;
}
fh = a.nextFileHeader();
}
a.close();
a = null;
}
catch(Exception e){
throw e;
}
finally{
if(fos != null)
{
try{
fos.close();
fos = null;
}
catch(Exception e){
e.printStackTrace();
}
}
if(a != null)
{
try{
a.close();
a = null;
}
catch(Exception e){
e.printStackTrace();
}
}
}
}

public static void doCompress(String srcFile,String destDir) throws Exception
{
//保证文件夹路径最后是"\"或者"/"
char lastChar = destDir.charAt(destDir.length()-1);
if(lastChar != '\\' && lastChar != '/')
{
destDir += File.separator;
}
//根据类型进行相应的解压
String type = srcFile.substring(srcFile.lastIndexOf(".")+1);
if(type.endsWith("zip"))
{
unZip(srcFile,destDir);
}
else if(type.endsWith("rar"))
{
UnRarUtil.unRar(srcFile, destDir);
}
else
{
throw new Exception("只支持zip和rar格式的压缩包!");
}
}

public static void unZip(String unZipfileName, String mDestPath) {
if (!mDestPath.endsWith("/"))
{
mDestPath = mDestPath + "/";
}
FileOutputStream fileOut = null;
ZipInputStream zipIn = null;
ZipEntry zipEntry = null;
File file = null;
int readedBytes = 0;
byte buf[] = new byte[4096];
try {
zipIn = new ZipInputStream(new BufferedInputStream(new FileInputStream(unZipfileName)));

while ((zipEntry = zipIn.getNextEntry()) != null)
{
file = new File(mDestPath + zipEntry.getName());
if (zipEntry.isDirectory())
{
file.mkdirs();
} else
{
// 如果指定文件的目录不存在,则创建之.
File parent = file.getParentFile();
if (!parent.exists())
{
parent.mkdirs();
}
fileOut = new FileOutputStream(file);
while ((readedBytes = zipIn.read(buf)) > 0)
{
fileOut.write(buf, 0, readedBytes);
}
fileOut.close();
}
zipIn.closeEntry();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}

// public static void unZip(String zipfile, String destDir)
// {
// byte b[] = new byte [1024];
// int length;
// ZipFile zipFile;
// try {
//
// zipFile = new ZipFile( new File(zipfile,"GBK"));
//
// Enumeration<?> enumeration = zipFile.getEntries();
// ZipEntry zipEntry = null ;
// while (enumeration.hasMoreElements())
// {
// zipEntry = (ZipEntry) enumeration.nextElement();
// File loadFile = new File(destDir + zipEntry.getName());
//
//
//
// if (zipEntry.isDirectory()) {
//
// // 这段都可以不要,因为每次都貌似从最底层开始遍历的
//
// loadFile.mkdirs();
//
// } else {
//
// if (!loadFile.getParentFile().exists())
//
// loadFile.getParentFile().mkdirs();
//
//
//
// OutputStream outputStream = new FileOutputStream(loadFile);
//
// InputStream inputStream = zipFile.getInputStream(zipEntry);
//
//
//
// while ((length = inputStream.read(b)) > 0)
//
// outputStream.write(b, 0, length);
//
//
//
// }
//
// }
//
// System. out .println( " 文件解压成功 " );
//
// } catch (IOException e) {
//
// // TODO Auto-generated catch block
//
// e.printStackTrace();
//
// }
//
//
//
// }







}
...全文
1023 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
xaqk008 2012-04-16
  • 打赏
  • 举报
回复
晕 明天还没解决的话就结贴。。。。。。。。。。。。。。。。。。。。。
xaqk008 2012-04-13
  • 打赏
  • 举报
回复
楼上说的类具体怎么用啊 麻烦给出代码 谢谢了
xaqk008 2012-04-13
  • 打赏
  • 举报
回复
我说的是文件中文内容乱码,不是中文文件名乱码。
MiceRice 2012-04-12
  • 打赏
  • 举报
回复
其实还是字符集问题,参考下这里解决吧:
http://hi.baidu.com/wqj403/blog/item/b90b2537c73c7e380855a962.html
xaqk008 2012-04-12
  • 打赏
  • 举报
回复
额 上面错了 是回答的3楼
xaqk008 2012-04-12
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
我用的方法是直接复制出jdk中的那个ZipOutputStream类,然后改写下那个写入文件名的部分,具体可以谷歌百度
[/Quote]

是“GBK”
xaqk008 2012-04-12
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
我用的方法是直接复制出jdk中的那个ZipOutputStream类,然后改写下那个写入文件名的部分,具体可以谷歌百度
[/Quote]

具体怎么改的?可以给出代码吗?
MiceRice 2012-04-12
  • 打赏
  • 举报
回复
确认下压缩时用的是什么字符集,是不是UTF-8?
zj304292653 2012-04-12
  • 打赏
  • 举报
回复
我用的方法是直接复制出jdk中的那个ZipOutputStream类,然后改写下那个写入文件名的部分,具体可以谷歌百度
xaqk008 2012-04-12
  • 打赏
  • 举报
回复
没人回答吗?自己顶下。
zj304292653 2012-04-12
  • 打赏
  • 举报
回复
  
/**
* 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 (current != 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:
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");
}
break;
default:
throw new ZipException("unsupported compression method");
}
if (!names.add(e.name))
{
throw new ZipException("duplicate entry: " + e.name);
}
current = new XEntry(e, written);
xentries.add(current);
writeLOC(current);
}

/**
* 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();
if (current != null)
{
ZipEntry e = current.entry;
switch (e.method)
{
case DEFLATED:
def.finish();
while (!def.finished())
{
deflate();
}
if ((current.flag & 8) == 0)
{
// verify size, compressed size, and crc-32 settings
if (e.size != def.getBytesRead())
{
throw new ZipException("invalid entry size (expected " + e.size + " but got "
+ def.getBytesRead() + " bytes)");
}
if (e.csize != def.getBytesWritten())
{
throw new ZipException("invalid entry compressed size (expected " + e.csize + " but got "
+ def.getBytesWritten() + " 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.getBytesRead();
e.csize = def.getBytesWritten();
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 ZipException("invalid compression method");
}
crc.reset();
current = 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 (current == null)
{
throw new ZipException("no current ZIP entry");
}
ZipEntry entry = current.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 ZipException("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 (current != null)
{
closeEntry();
}
if (xentries.size() < 1)
{
throw new ZipException("ZIP file must have at least one entry");
}
// write central directory
long off = written;
for (XEntry xentry : xentries)
writeCEN(xentry);
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(XEntry xentry)
throws IOException
{
ZipEntry e = xentry.entry;
int flag = xentry.flag;
writeInt(LOCSIG); // LOC header signature
writeShort(version(e)); // version needed to extract
writeShort(flag); // general purpose bit flag
writeShort(e.method); // compression method
writeInt(e.time); // last modification time
if ((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 = null;
if ("UTF-8".equalsIgnoreCase(fileNameEncoding))
{
nameBytes = getUTF8Bytes(e.name);
}
else
{
nameBytes = e.name.getBytes(fileNameEncoding);
}
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
}

zj304292653 2012-04-12
  • 打赏
  • 举报
回复
   
/**
* 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);
}
zj304292653 2012-04-12
  • 打赏
  • 举报
回复
package com.*.*.server.resource.utils;

import java.io.OutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.Vector;
import java.util.HashSet;
import java.util.zip.CRC32;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.ZipException;

/**
*
*此类从JDK中复制出来,添加了对中文文件名的支持
*
* @author zengj
* @version [版本号, 2012-2-9]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class CNZipOutPutStream extends DeflaterOutputStream implements ZipConstants
{

private static class XEntry
{
public final ZipEntry entry;

public final long offset;

public final int flag;

public XEntry(ZipEntry entry, long offset)
{
this.entry = entry;
this.offset = offset;
this.flag = (entry.method == DEFLATED && (entry.size == -1 || entry.csize == -1 || entry.crc == -1))
// store size, compressed size, and crc-32 in data descriptor
// immediately following the compressed entry data
? 8
// store size, compressed size, and crc-32 in LOC header
: 0;
}
}

private XEntry current;

private Vector<XEntry> xentries = new Vector<XEntry>();

private HashSet<String> names = new HashSet<String>();

private CRC32 crc = new CRC32();

private long written = 0;

private long locoff = 0;

private String comment;

private int method = DEFLATED;

private boolean finished;

private boolean closed = false;

private String fileNameEncoding = "UTF-8";

private static int version(ZipEntry e)
throws ZipException
{
switch (e.getMethod())
{
case DEFLATED:
return 20;
case STORED:
return 10;
default:
throw new ZipException("unsupported compression method");
}
}

/**
* Checks 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 CNZipOutPutStream(OutputStream out)
{
super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
try
{
Field f = this.getClass().getDeclaredField("usesDefaultDeflater");
f.setAccessible(true);
f.set(this, true);
}
catch (NoSuchFieldException e)
{ // Ignore
}
catch (IllegalAccessException e)
{// Ignore
}
}

/**
*此方法扩展了JDK的ZIP压缩输出流的默认构造函数,添加了一个内部文件名编码参数
*/
public CNZipOutPutStream(OutputStream out, String fileNameEncoding)
{
this(out);
if (fileNameEncoding != null)
{
this.fileNameEncoding = fileNameEncoding;
}
}


62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧