如何在Xamarin for Android中压缩文件?

时间:2014-09-16 00:40:11

标签: c# android xamarin zip filestream

我有一个函数可以创建一个zip文件,传递一个文件的字符串数组。该函数确实成功创建了zip文件及其中的zip条目文件,但这些zip条目文件为空。我尝试了几种不同的方法 - 下面的功能代码是我最接近工作的代码:

    public static bool ZipFile(string[] arrFiles, string sZipToDirectory, string sZipFileName)
    {
        if (Directory.Exists(sZipToDirectory))
        {
            FileStream fNewZipFileStream;
            ZipOutputStream zos;

            try {
                fNewZipFileStream = File.Create(sZipToDirectory + sZipFileName);
                zos = new ZipOutputStream(fNewZipFileStream);

                for (int i = 0; i < arrFiles.Length; i++) {
                    ZipEntry entry = new ZipEntry(arrFiles[i].Substring(arrFiles[i].LastIndexOf("/") + 1));
                    zos.PutNextEntry(entry);

                    FileStream fStream = File.OpenRead(arrFiles[i]);
                    BufferedStream bfStrm = new BufferedStream(fStream);

                    byte[] buffer = new byte[bfStrm.Length];
                    int count;
                    while ((count = bfStrm.Read(buffer, 0, 1024)) != -1) {
                        zos.Write(buffer);
                    }

                    bfStrm.Close();
                    fStream.Close();
                    zos.CloseEntry();
                }
                zos.Close();
                fNewZipFileStream.Close();
                return true;
            }
            catch (Exception ex)
            {
                string sErr = ex.Message;
                return false;
            }
            finally
            {
                fNewZipFileStream = null;
                zos = null;
            }
        }
        else
        {
            return false;
        }
    }

我认为这与字节流处理有关。我已经尝试了一些处理流的代码,但它进入了无限循环:

while ((count = fStream.Read(buffer, 0, 1024)) != -1) {
        zos.Write(buffer, 0, count);
}
fStream.Close();

4 个答案:

答案 0 :(得分:2)

Read()上使用FileStream会返回读入流中的字节数,如果已到达流末尾,则返回0。它永远不会返回值-1。

来自MSDN

The total number of bytes read into the buffer. This might be less than the number of bytes requested if that number of bytes are not currently available, or zero if the end of the stream is reached

我会将您的代码修改为以下内容:

System.IO.FileStream fos = new System.IO.FileStream(sZipToDirectory + sZipFileName, FileMode.Create);
Java.Util.Zip.ZipOutputStream zos = new Java.Util.Zip.ZipOutputStream(fos);

byte[] buffer = new byte[1024];
for (int i = 0; i < arrFiles.Length; i++) {

    FileInfo fi = new FileInfo (arrFiles[i]);
    Java.IO.FileInputStream fis = new Java.IO.FileInputStream(fi.FullName);

    ZipEntry entry = new ZipEntry(arrFiles[i].Substring(arrFiles[i].LastIndexOf("/") + 1));
    zos.PutNextEntry(entry);

    int count = 0;
    while ((count = fis.Read(buffer)) > 0) {
        zos.Write(buffer, 0, count);
    }

    fis.Close();
    zos.CloseEntry();
}

这与我过去在Android上创建zip档案时使用的代码几乎相同。

答案 1 :(得分:2)

我找到了一个非常简单的解决方案 - 我使用了静态File类的ReadAllBytes方法。

ZipEntry entry = new ZipEntry(arrFiles[i].Substring(arrFiles[i].LastIndexOf("/") + 1));
zos.PutNextEntry(entry);

byte[] fileContents = File.ReadAllBytes(arrFiles[i]);
zos.Write(fileContents);
zos.CloseEntry();

答案 2 :(得分:0)

您是否可以使用SharpZip?它真的很容易使用。

这是a blog post我写的提取zip文件

    private static void upzip(string url)
    {
        WebClient wc = new WebClient();
        wc.DownloadFile(url, "temp.zip");  
        //unzip
        ZipFile zf = null;
        try
        {
            zf = new ZipFile(File.OpenRead("temp.zip"));
            foreach (ZipEntry zipEntry in zf)
            {
                string fileName = zipEntry.Name;
                byte[] buffer = new byte[4096];
                Stream zipStream = zf.GetInputStream(zipEntry);
                using (FileStream streamWriter = File.Create( fileName))
                {
                    StreamUtils.Copy(zipStream, streamWriter, buffer);
                }
            }

        }
        finally
        {
            if (zf != null)
            {
                zf.IsStreamOwner = true;
                zf.Close();
            }
        }

    }

答案 3 :(得分:0)

private void ZipFolder(string[] _files, string zipFileName)
    {
        using var memoryStream = new MemoryStream();
        using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
        {
            foreach (var item in _files)
            {
                var demoFile = archive.CreateEntry(Path.GetFileName(item));
                using var readStreamW = File.OpenRead(item);
                using (var entryStream = demoFile.Open())
                {
                    using (var streamWriter = new StreamWriter(entryStream))
                    {
                        readStreamW.Seek(0, SeekOrigin.Begin);
                        readStreamW.CopyTo(streamWriter.BaseStream);
                    }
                }
            }
        }

        using var fileStream = new FileStream(zipFileName, FileMode.Create);
        memoryStream.Seek(0, SeekOrigin.Begin);
        memoryStream.CopyTo(fileStream);
    }