tags:

views:

292

answers:

3

I am using the SharpZipLib open source .net library from www.icsharpcode.net

My goal is to unzip an xml file and read it into a dataset. However I get the following error reading the file into a dataset: "Data at the root level is invalid. Line 1, position 1." I believe what is happening is the unzipping code is not releasing the file for the following reasons.

1.) If I unzip the file and exit the application. When I restart the app I CAN read the unzipped file into a dataset. 2.) If I read in the xml file right after writing it out (no zipping) then it works fine.
3.) If I write the dataset to xml, zip it up, unzip it, then attempt to read it back in I get the exception.

The code below is pretty straight forward. UnZipFile will return the name of the file just unzipped. Right below this call is the call to read it into a dataset. The variable fileToRead is the full path to the newly unzipped xml file.

string fileToRead = UnZipFile(filepath, DOViewerUploadStoreArea);
ds.ReadXml(fileToRead )

private string UnZipFile(string file, string dirToUnzipTo)
{

       string unzippedfile = "";

        try
        {
            ZipInputStream s = new ZipInputStream(File.OpenRead(file));
            ZipEntry myEntry;
            string tmpEntry = String.Empty;
            while ((myEntry = s.GetNextEntry()) != null)
            {
                string directoryName = dirToUnzipTo;
                string fileName = Path.GetFileName(myEntry.Name);
                string fileWDir = directoryName + fileName;
                unzippedfile = fileWDir;

                FileStream streamWriter = File.Create(fileWDir);
                int size = 4096;
                byte[] data = new byte[4096];
                while (true)
                {
                    size = s.Read(data, 0, data.Length);
                    if (size > 0) { streamWriter.Write(data, 0, size); }
                    else { break; }
                }
                streamWriter.Close();
            }
            s.Close();
        }
        catch (Exception ex)
        {
            LogStatus.WriteErrorLog(ex, "ERROR", "DOViewer.UnZipFile");

        }
        return (unzippedfile);
    }
+1  A: 

Well, what does the final file look like? (compared to the original). You don't show the zipping code, which might be part of the puzzle, especially as you are partially swallowing the exception.

I would also try ensuring everything IDisposable is Dispose()d, ideally via using; also - in case the problem is with path construction, use Path.Combine. And note that if myEntry.Name contains sub-directories, you will need to create them manually.

Here's what I have - it works for unzipping ICSharpCode.SharpZipLib.dll:

    private string UnZipFile(string file, string dirToUnzipTo)
    {

        string unzippedfile = "";

        try
        {
            using(Stream inStream = File.OpenRead(file))
            using (ZipInputStream s = new ZipInputStream(inStream))
            {
                ZipEntry myEntry;
                byte[] data = new byte[4096];
                while ((myEntry = s.GetNextEntry()) != null)
                {
                    string fileWDir = Path.Combine(dirToUnzipTo, myEntry.Name);
                    string dir = Path.GetDirectoryName(fileWDir);
                    // note only supports a single level of sub-directories...
                    if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
                    unzippedfile = fileWDir; // note; returns last file if multiple

                    using (FileStream outStream = File.Create(fileWDir))
                    {
                        int size;
                        while ((size = s.Read(data, 0, data.Length)) > 0)
                        {
                            outStream.Write(data, 0, size);
                        }
                        outStream.Close();
                    }
                }
                s.Close();
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);

        }
        return (unzippedfile);
    }

It could also be that the problem is either in the code that writes the zip, or the code that reads the generated file.

Marc Gravell
A: 

I compared the original with the final using TextPad and they are identical. Also I rewrote the code to take advantage of the using. Here is the code. My issue seems to be centered around file locking or something. If I unzip the file quit the application then start it up it will read find.

private string UnZipFile(string file, string dirToUnzipTo)
    {
        string unzippedfile = "";

        try
        {
            using (ZipInputStream s = new ZipInputStream(File.OpenRead(file)))
            {

                ZipEntry theEntry;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    string directoryName = dirToUnzipTo;
                    string fileName = Path.GetFileName(theEntry.Name);
                    string fileWDir = directoryName + fileName;
                    unzippedfile = fileWDir;

                    if (fileName != String.Empty)
                    {
                        using (FileStream streamWriter = File.Create(fileWDir))
                        {
                            int size = 2048;
                            byte[] data = new byte[2048];
                            while (true)
                            {
                                size = s.Read(data, 0, data.Length);
                                if (size > 0)
                                {
                                    streamWriter.Write(data, 0, size);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            LogStatus.WriteErrorLog(ex, "ERROR", "DOViewer.UnZipFile");

        }
        return (unzippedfile);
    }
Ron Skufca
A: 

This is a lot simpler to do with DotNetZip.

using (ZipFile zip = ZipFile.Read(ExistingZipFile))
{
     zip.ExtractAll(TargetDirectory);       
}

If you want to decide on which files to extract ....

using (ZipFile zip = ZipFile.Read(ExistingZipFile))
{
    foreach (ZipEntry e in zip)
    {
        if (wantThisFile(e.FileName)) e.Extract(TargetDirectory);
    }
}

If you would like to overwrite existing files during extraction:

using (ZipFile zip = ZipFile.Read(ExistingZipFile))
{
     zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.OverwriteSilently);
}

Or, to extract password-protected entries:

using (ZipFile zip = ZipFile.Read(ExistingZipFile))
{
     zip.Password = "Shhhh, Very Secret!";
     zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.OverwriteSilently);
}
Cheeso