简体   繁体   中英

How do I zip files in Xamarin for Android?

I have a function that creates a zip file a string array of files passed. The function does succeed in creating the zip file and the zip entry files inside it, but these zip entry files are empty. I've tried a couple of different methods - the function code below is the closest I've gotten to something working:

    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;
        }
    }

I think it's got to do with the byte stream handling. I've tried this bit of code that handles the stream but it goes into an infinite loop:

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

I found a solution that is quite simple - I used the ReadAllBytes method of the static File class.

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();

Using Read() on a FileStream returns the amount of bytes read into the stream or 0 if the end of the stream has been reached. It will never return a value of -1.

From 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 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 .

I'd modify your code to the following:

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();
}

This is nearly identical to the code I've used for creating zip archives on Android in the past.

Are you allowed to use SharpZip ? It's really easy to use.

Here is a blog post I wrote to extract zip files

    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();
            }
        }

    }
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);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM