C#压缩文件Java解压文件
源起:最近在做项目时遇到C#和java交互文件处理,C#使用 ICSharpCode.SharpZipLib将文件压缩,Java使用java.util.zip解压文件,前提要求java解压时必须使用UTF-8的编码格式,因此也就需要C#压缩文件时使用UTF-8编码(那么不使用会出现什么问题?)
这个问题其实就涉及到了一些编码的问题,常见的我们都知道ASCII、GBK、UTF-8等等。。。
那么为什么会乱码,根本原因就是字节不同导致在解读时产生了不同的解读方式,这里给大家分享一篇文章
https://www.cnblogs.com/flashsun/p/13975316.html(闪客sun)讲述的很详细,有兴趣的话可以了解一下.
回归正题
如果你阅读了上面的文章你应该已经了解了为什么会乱码(默认你们都看过了)
那么我们来看一下如何造成的这种问题先看一下压缩文件的代码
使用C#的ICSharpCode.SharpZipLib库
/// <summary>
/// 文件压缩
/// </summary>
/// <param name="sourceFilePath">源文件</param>
/// <param name="destinationZipFilePath">目标路径</param>
public static void CreateZip(string sourceFilePath, string destinationZipFilePath)
{
if (sourceFilePath[sourceFilePath.Length - 1] != System.IO.Path.DirectorySeparatorChar)
sourceFilePath += System.IO.Path.DirectorySeparatorChar;
ZipOutputStream zipStream = new ZipOutputStream(File.Create(destinationZipFilePath));
zipStream.SetLevel(6); // 压缩级别 0-9
CreateZipFiles(sourceFilePath, zipStream, sourceFilePath);
zipStream.Finish();
zipStream.Close();
}
/// <summary>
/// 递归压缩文件
/// </summary>
/// <param name="sourceFilePath"></param>
/// <param name="zipStream"></param>
/// <param name="staticFile"></param>
private static void CreateZipFiles(string sourceFilePath, ZipOutputStream zipStream, string staticFile)
{
Crc32 crc = new Crc32();
string[] filesArray = Directory.GetFileSystemEntries(sourceFilePath);
foreach (string file in filesArray)
{
if (Directory.Exists(file)) //如果当前是文件夹,递归
{
CreateZipFiles(file, zipStream, staticFile);
}
else //如果是文件,开始压缩
{
FileStream fileStream = File.OpenRead(file);
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, buffer.Length);
string tempFile = file.Substring(staticFile.LastIndexOf("\\") + 1);
ZipEntry entry = new ZipEntry(tempFile);
entry.DateTime = DateTime.Now;
entry.Size = fileStream.Length;
fileStream.Close();
crc.Reset();
crc.Update(buffer);
entry.Crc = crc.Value;
zipStream.PutNextEntry(entry);
zipStream.Write(buffer, 0, buffer.Length);
}
}
}
下面再看一下Java 解压文件的代码
使用的是java.util.zip类库
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
try {
ZipInputStream Zin = new ZipInputStream(new FileInputStream("输入源zip路径"));//输入源zip路径
BufferedInputStream Bin = new BufferedInputStream(Zin);
String Parent = "输出路径"; //输出路径(文件夹目录)
File Fout = null;
ZipEntry entry;
try {
while ((entry = Zin.getNextEntry()) != null ) {
if (!entry.isDirectory()) {
Fout = new File(Parent, entry.getName());
if (!Fout.exists()) {
(new File(Fout.getParent())).mkdirs();
}
FileOutputStream out = new FileOutputStream(Fout);
BufferedOutputStream Bout = new BufferedOutputStream(out);
int b;
while ((b = Bin.read()) != -1) {
Bout.write(b);
}
Bout.close();
out.close();
System.out.println(Fout + "解压成功");
}
}
Bin.close();
Zin.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("耗费时间: " + (endTime - startTime) + " ms");
}
使用以上的代码压缩解压后Java报错(前提是要解压缩的文件中包含中文)
Exception in thread “main” java.lang.IllegalArgumentException: malformed input off : 1, length : 1
at java.base/java.lang.StringCoding.throwMalformed(StringCoding.java:698)
at java.base/java.lang.StringCoding.decodeUTF8_0(StringCoding.java:781)
at java.base/java.lang.StringCoding.newStringUTF8NoRepl(StringCoding.java:978)
at java.base/java.lang.System 2. n e w S t r i n g U T F 8 N o R e p l ( S y s t e m . j a v a : 2267 ) a t j a v a . b a s e / j a v a . u t i l . z i p . Z i p C o d e r 2.newStringUTF8NoRepl(System.java:2267) at java.base/java.util.zip.ZipCoder 2.newStringUTF8NoRepl(System.java:2267)atjava.base/java.util.zip.ZipCoderUTF8ZipCoder.toString(ZipCoder.java:208)
at java.base/java.util.zip.ZipCoder.toString(ZipCoder.java:66)
at java.base/java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:302)
at java.base/java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:124)
at demo.CopyOfMyzipDecompressing.main(CopyOfMyzipDecompressing.java:22)
Caused by: java.nio.charset.MalformedInputException: Input length = 1
… 9 more
出现报错原因是:C#默认编码为GBK而java.util.zip默认是UTF-8编码所以在导致解压报错,那么要解决问题根本原因在于让C#解压是使用UTF-8编码
找到问题原因了,那么我们只要解决压缩的时候把编码设置为UTF-8就可以了
ICSharpCode.SharpZipLib库没有很明显的设置编码的方法,比如java.util.zip库就很明显的提供了两个方法可以设置编码格式,
而C#类库中就没有这种方法
没办法现在要么网上找资料,要么去官网查文档或者看源码
当然本着学习的精神我们直接找到源码看一下,通过上面的代码我们可以发现主要就是 PutNextEntry在做压缩这件事情
这里不带大家每行代码去看了 直接给出关键的位置ConvertToArray
可以看到这里使用的编码方式就是ZipConstants.DefaultCodePage这个属性,那么解决方案就有了 我们直接改掉这个属性就可以了
Encoding gbk = Encoding.GetEncoding("UTF-8");
ZipConstants.DefaultCodePage = gbk.CodePage;
试一下发现果然解决问题了,但是在最新的dll中这个属性已经过时了,那是不是有其他方法?
再回去看我们可以发现ConvertToArray有两个方法重载
这里竟然有UTF-8的编码,看来作者已经考虑到了问题并提供了新的方案,所以这里这要让flags传值就可以了最后的代码是
/// <summary>
/// 文件压缩
/// </summary>
/// <param name="sourceFilePath">源文件</param>
/// <param name="destinationZipFilePath">目标路径</param>
public static void CreateZip(string sourceFilePath, string destinationZipFilePath)
{
if (sourceFilePath[sourceFilePath.Length - 1] != System.IO.Path.DirectorySeparatorChar)
sourceFilePath += System.IO.Path.DirectorySeparatorChar;
ZipOutputStream zipStream = new ZipOutputStream(File.Create(destinationZipFilePath));
zipStream.SetLevel(6); // 压缩级别 0-9
CreateZipFiles(sourceFilePath, zipStream, sourceFilePath);
zipStream.Finish();
zipStream.Close();
}
/// <summary>
/// 递归压缩文件
/// </summary>
/// <param name="sourceFilePath"></param>
/// <param name="zipStream"></param>
/// <param name="staticFile"></param>
private static void CreateZipFiles(string sourceFilePath, ZipOutputStream zipStream, string staticFile)
{
Crc32 crc = new Crc32();
string[] filesArray = Directory.GetFileSystemEntries(sourceFilePath);
foreach (string file in filesArray)
{
if (Directory.Exists(file)) //如果当前是文件夹,递归
{
CreateZipFiles(file, zipStream, staticFile);
}
else //如果是文件,开始压缩
{
FileStream fileStream = File.OpenRead(file);
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, buffer.Length);
string tempFile = file.Substring(staticFile.LastIndexOf("\\") + 1);
ZipEntry entry = new ZipEntry(tempFile);
entry.DateTime = DateTime.Now;
entry.Size = fileStream.Length;
entry.Flags = 2048;
fileStream.Close();
crc.Reset();
crc.Update(buffer);
entry.Crc = crc.Value;
zipStream.PutNextEntry(entry);
zipStream.Write(buffer, 0, buffer.Length);
}
}
}
到此这个问题已经完美解决了,很简单的问题但是从中可以看到自己很多不足之处, 努力吧 打工人!!!
转载:https://blog.csdn.net/qq_38251913/article/details/113859882