GZipStream抱怨头部的魔数不正确

10
我正在尝试使用美国国家气象局的数据,但最近有些变化,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)

我不明白发生了什么变化,但这成为了一个真正的停工问题。有经验的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);
}

是的,两个文件都没问题。你是怎么获取这个文件的? - Mark Adler
抱歉——我之前发布的失败URL是错误的。附上示例代码。 - jocull
工作和不工作文件的链接不再有效。 - Javier Ruiz
@JavierRuiz 我认为文件内容现在并不特别相关。请检查已接受的答案 - 我相信当时服务器返回了格式不正确的数据。 - jocull
2个回答

11

看起来这个服务有时会返回伪装成.tar.gztar格式文件,这很令人困惑。但是,如果你检查前两个字节是否为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
    }
}

2
天啊,这些愚蠢的qpe文件给我带来了严重的麻烦。此消息应标记为“错误GZIP头,第一个幻数字节不匹配”和“GZip头中的幻数不正确。确保您正在传递GZip流。”非常感谢您解决了这个问题! - David
1
从Google Cloud Platform存储桶下载到我的Windows机器的ZIP文件也有同样的问题:它们具有.gz扩展名,但7ZIP信息告诉我它们实际上是zip文件。 - Francesco B.

-4

[已解决] GZipStream 抱怨头中的魔数不正确

//异常魔数 tar.gz 文件

引起的魔法错误

  1. 文件未正确压缩为 tar.gz
  2. 文件大小过大,超过 1GB

解决方案

  1. 使用 .net framework 4.5.1 来解决此异常 //或者//

  2. 在不更改 .net framework 的情况下操作现有解决方案。请按照以下步骤进行实施。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接