GZipStream 抱怨 header 中的幻数不正确

GZipStream complains magic number in header is not correct

我正在尝试使用国家气象局 (U.S.) 数据,但最近发生了一些变化,GZip 文件不再打开。

.NET 4.5 抱怨...

Message=The magic number in GZip header is not correct. Make sure you are passing in a GZip stream.
Source=System
StackTrace:
   at System.IO.Compression.GZipDecoder.ReadHeader(InputBuffer input)
   at System.IO.Compression.Inflater.Decode()
   at System.IO.Compression.Inflater.Inflate(Byte[] bytes, Int32 offset, Int32 length)
   at System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count)

我不明白发生了什么变化,但这正在成为现实 show-stopper。任何有 GZip 格式经验的人都可以告诉我发生了什么变化使它停止工作吗?

有效的文件:

http://www.srh.noaa.gov/ridge2/Precip/qpehourlyshape/2015/201504/20150404/nws_precip_2015040420.tar.gz

一个不起作用的文件:

http://www.srh.noaa.gov/ridge2/Precip/qpehourlyshape/2015/201505/20150505/nws_precip_2015050505.tar.gz

更新示例代码

const string url = "http://www.srh.noaa.gov/ridge2/Precip/qpehourlyshape/2015/201505/20150505/nws_precip_2015050505.tar.gz";
string appPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string downloadPath = Path.Combine(appPath, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "nws_precip_2015050505.tar.gz");
using (var wc = new WebClient())
{
    wc.DownloadFile(url, downloadPath);
}

string extractDirPath = Path.Combine(appPath, "Extracted");
if (!Directory.Exists(extractDirPath))
{
    Directory.CreateDirectory(extractDirPath);
}
string extractFilePath = Path.Combine(extractDirPath, "nws_precip_2015050505.tar");

using (var fsIn = new FileStream(downloadPath, FileMode.Open, FileAccess.Read))
using (var fsOut = new FileStream(extractFilePath, FileMode.Create, FileAccess.Write))
using (var gz = new GZipStream(fsIn, CompressionMode.Decompress, true))
{
    gz.CopyTo(fsOut);
}

似乎此服务有时 returns tar 格式文件伪装成 .tar.gz。这非常令人困惑,但是如果您检查前两个字节是 0x1F0x8B,您可以通过手动检查其幻数来检测该文件是否为 GZip。

using (FileStream fs = new FileStream(downloadPath, FileMode.Open, FileAccess.Read))
{
    byte[] buffer = new byte[2];
    fs.Read(buffer, 0, buffer.Length);
    if (buffer[0] == 0x1F
        && buffer[1] == 0x8B)
    {
        // It's probably a GZip file
    }
    else
    {
        // It's probably not a GZip file
    }
}

[已解决] GZipStream 抱怨 header 中的幻数不正确

//异常幻数tar.gz 文件

错误原因

  1. 文件未正确压缩到 tar.gz
  2. 文件太大,超过 1+GB

解决了

  1. 使用 .net framework 4.5.1 解决这个异常 //OR//

  2. 在不更改 .net 框架的情况下修改现有解决方案。 请按步骤执行。

    1. 将 abc.tar.gz 改成 abc(删除扩展名)。

    2. 传这个文件直接命名为压缩函数

*public static void Compress(DirectoryInfo directorySelected, string directoryPath)

    {
        foreach (FileInfo fileToCompress in directorySelected.GetFiles())
        {
            using (FileStream originalFileStream = fileToCompress.OpenRead())
            {
                if ((File.GetAttributes(fileToCompress.FullName) &
                   FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".tar.gz")
                {
                    using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".tar.gz"))
                    {
                        using (System.IO.Compression.GZipStream compressionStream = new System.IO.Compression.GZipStream(compressedFileStream,
                           System.IO.Compression.CompressionMode.Compress))
                        {
                            originalFileStream.CopyTo(compressionStream);
                        }
                    }
                    FileInfo info = new FileInfo(directoryPath + "\" + fileToCompress.Name + ".tar.gz");
                }
            }
        }
    }


3. implement this code in following exception handler try catch block
    try
    {
        TarGzFilePath=@"c:\temp\abc.tar.gz";
        FileStream streams = File.OpenRead(TarGzFilePath);
        string FileName=string.Empty;
        GZipInputStream tarGz = new GZipInputStream(streams);
        TarInputStream tar = new TarInputStream(tarGz);
        // exception will occured in below lines should apply try catch

        TarEntry ze;
            try
            {
                ze = tar.GetNextEntry();// exception occured here "magical number"
            }
            catch (Exception extra)
            {
                tar.Close();
                tarGz.Close();
                streams.Close();
                //please close all above , other wise it will come with exception "tihs process use by another process"
                //rename your file *for better accuracy you can copy file to other location 

                File.Move(@"c:\temp\abc.tar.gz", @"c:\temp\abc"); // rename file 
                DirectoryInfo directorySelected = new DirectoryInfo(Path.GetDirectoryName(@"c:\temp\abc"));
                Compress(directorySelected, directoryPath); // directorySelected=c:\temp\abc , directoryPath=c:\temp\abc.tar.gz // process in step 2 function 
                streams = File.OpenRead(TarGzFilePath);
                tarGz = new GZipInputStream(streams);
                tar = new TarInputStream(tarGz);
                ze = tar.GetNextEntry();                    
            }
            // do anything with extraction with your code
    }
    catch (exception ex)
    {
        tar.Close();
        tarGz.Close();
        streams.Close();
    }