Vra

Ek lees 'n Gz lêer van 'n paar stadige bron (soos FTP Server) en is die verwerking van die ontvang data dadelik. Lyk iets soos hierdie:

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)
  {
    ...
  }
}

My probleem is wat 'n akkurate progress bar. Vooruit kan ek die saamgeperste Gz lêergrootte kry, maar ek het geen idee hoe groot die inhoud sou word ongecomprimeerd. Lees die lêer reël vir reël ek weet baie goed hoeveel ongecomprimeerd grepe ek lees, maar ek weet nie hoe dit hou verband met die saamgeperste lêer grootte.

So, is daar geen manier uit GZipStream te kry hoe ver die lêer wyser is gevorderde in die saamgeperste lêer? Ek hoef net die huidige posisie, die GZ lêer grootte Ek kan haal voor die lees van die lêer.

Was dit nuttig?

Oplossing

Jy kan 'n stroom in tussen wat tel, hoeveel grepe GZipStream gelees het prop.

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

Ander wenke

Ek stel voor dat jy 'n blik op die volgende kode te neem:

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

Ek het my kode herbesoek en ek het 'n paar toetse uitgevoer. IMHO Darin is reg. Maar ek dink dit is moontlik om net die kop (grootte?) Van die zipped stroom lees en uit te vind die lêer grootte. (WinRar "weet" wat die uitgepakte lêergrootte sonder pak die hele rits argief. Dit lui hierdie inligting uit kop argief se.) As jy die lêer grootte hierdie kode sal jou help om 'n presiese vorderingsverslag vind.

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

Ek hoop dit help.

As 'n volmag vir decompressie vordering kan jy probeer om die inligting te kry vir lêer se aflaai vordering van die onderliggende stroom met behulp:

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

of

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

Dit werk op 'n FileStream en dit moet werk op 'n GetResponseStream ( ) op voorwaarde dat dit implemente Posisie eiendom en die FTP-bediener terugkeer inligting oor die lengte van die lêer se: http://msdn.microsoft.com/en-us/library/system.net.ftpwebresponse.contentlength (v = vs.110) Aspx

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top