Frage

Ich bin eine .gz-Datei von einer langsamen Quelle zu lesen (wie FTP-Server) und bin sofort zum den empfangenen Daten. Sieht so etwas wie folgt aus:

FtpWebResponse response = ftpclientRequest.GetResponse() as FtpWebResponse;
using (Stream ftpStream = response.GetResponseStream())
using (GZipStream unzipped = new GZipStream(ftpStream, CompressionMode.Decompress))
using (StreamReader linereader = new StreamReader(unzipped))
{
  String l;
  while ((l = linereader.ReadLine()) != null)
  {
    ...
  }
}

Mein Problem ist, zeigt ein genauen Fortschrittsbalken. Im Vorfeld kann ich die komprimierte .gz Dateigröße erhalten, aber ich habe keine Ahnung, wie groß der Inhalt dekomprimiert werden würde. Lesen Sie die Datei Zeile für Zeile ganz gut ich weiß, wie viele Bytes unkomprimierte ich gelesen, aber ich weiß nicht, wie diese auf die komprimierte Dateigröße bezieht.

So

, ist es eine Möglichkeit von GZipStream zu bekommen, wie weit der Dateizeiger in die komprimierte Datei vorgeschoben wird? Ich brauche nur die aktuelle Position, die gz Dateigröße ich vor dem Lesen Sie die Datei abrufen kann.

War es hilfreich?

Lösung

Sie können einen Strom anschließen, zwischen denen zählt, wie viele Bytes GZipStream gelesen hat.

  public class ProgressStream : Stream
  {
    public long BytesRead { get; set; }
    Stream _baseStream;
    public ProgressStream(Stream s)
    {
      _baseStream = s;
    }
    public override bool CanRead
    {
      get { return _baseStream.CanRead; }
    }
    public override bool CanSeek
    {
      get { return false; }
    }
    public override bool CanWrite
    {
      get { return false; }
    }
    public override void Flush()
    {
      _baseStream.Flush();
    }
    public override long Length
    {
      get { throw new NotImplementedException(); }
    }
    public override long Position
    {
      get
      {
        throw new NotImplementedException();
      }
      set
      {
        throw new NotImplementedException();
      }
    }
    public override int Read(byte[] buffer, int offset, int count)
    {
      int rc = _baseStream.Read(buffer, offset, count);
      BytesRead += rc;
      return rc;
    }
    public override long Seek(long offset, SeekOrigin origin)
    {
      throw new NotImplementedException();
    }
    public override void SetLength(long value)
    {
      throw new NotImplementedException();
    }
    public override void Write(byte[] buffer, int offset, int count)
    {
      throw new NotImplementedException();
    }
  }

// usage
FtpWebResponse response = ftpclientRequest.GetResponse() as FtpWebResponse;
using (Stream ftpStream = response.GetResponseStream())
using (ProgressStream progressStream = new ProgressStream(ftpstream))
using (GZipStream unzipped = new GZipStream(progressStream, CompressionMode.Decompress))
using (StreamReader linereader = new StreamReader(unzipped))
{
  String l;
  while ((l = linereader.ReadLine()) != null)
  {
    progressStream.BytesRead(); // does contain the # of bytes read from FTP so far.
  }
}

Andere Tipps

Ich schlage vor, Sie einen Blick auf den folgenden Code zu übernehmen:

public static readonly byte[] symbols = new byte[8 * 1024];

public static void Decompress(FileInfo inFile, FileInfo outFile)
{
    using (var inStream = inFile.OpenRead())
    {
        using (var zipStream = new GZipStream(inStream, CompressionMode.Decompress))
        {
            using (var outStream = outFile.OpenWrite())
            {
                var total = 0;
                do
                {
                    var async = zipStream.BeginRead(symbols, 0, symbols.Length, null, null);
                    total = zipStream.EndRead(async);
                    if (total != 0)
                    {
                        // Report progress. Read total bytes (8K) from the zipped file.
                        outStream.Write(symbols, 0, total);
                    }
                } while (total != 0);
            }
        }
    }
}

Ich habe meinen Code überarbeitet und ich habe einige Tests durchgeführt. IMHO Darin ist richtig. Aber ich denke, es ist möglich, nur die Header (Größe?) Des Reißverschluss Stream zu lesen und die resultierenden Dateigröße zu ermitteln. (WinRar „weiß“, was die entpackte Dateigröße, ohne die gesamte ZIP-Archiv zu entpacken. Es liest diese Informationen aus dem Archiv Header.) Wenn Sie die resultierende Datei Größe dieser Code wird dazu beitragen, finden Sie eine genaue Fortschritte Bericht zu erstatten.

public static readonly byte[] symbols = new byte[8 * 1024];

public static void Decompress(FileInfo inFile, FileInfo outFile, double size, Action<double> progress)
{
    var percents = new List<double>(100);

    using (var inStream = inFile.OpenRead())
    {
        using (var zipStream = new GZipStream(inStream, CompressionMode.Decompress))
        {
            using (var outStream = outFile.OpenWrite())
            {
                var current = 0;

                var total = 0;
                while ((total = zipStream.Read(symbols, 0, symbols.Length)) != 0)
                {
                    outStream.Write(symbols, 0, total);
                    current += total;

                    var p = Math.Round(((double)current / size), 2) * 100;
                    if (!percents.Contains(p))
                    {
                        if (progress != null)
                        {
                            progress(p);
                        }
                        percents.Add(p);
                    }
                }
            }
        }
    }
}

Ich hoffe, das hilft.

Als Proxy-Fortschritt zum Dekomprimieren Sie können versuchen, die Informationen für die Datei Download-Fortschritt von dem zugrunde liegenden Stream erhalten mit:

var percentageProgress = ftpStream.Position / (double)ftpWebResponse.ContentLength;

oder

var percentageProgress = ftpStream.Position / (double)ftpStream.Length;

Es funktioniert auf einem Filestream und es sollte Arbeit an einem GetResponseStream ( ), vorausgesetzt, es implementiert Position Eigenschaft und der FTP-Server gibt Informationen über die Länge der heruntergeladenen Datei: http://msdn.microsoft.com/en-us/library/system.net.ftpwebresponse.contentlength (v = vs.110) aspx

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top