문제

느린 소스 (FTP 서버와 같은)에서 .gz 파일을 읽고 있으며 수신 된 데이터를 즉시 처리하고 있습니다. 다음과 같이 보입니다.

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

내 문제는 정확한 진행률 표시 줄을 보여주는 것입니다. 미리 압축 된 .gz 파일 크기를 얻을 수 있지만 콘텐츠가 얼마나 큰지에 대한 단서는 얻지 못했습니다. 라인별로 파일을 읽는 것은 내가 읽은 비 압축 바이트 수를 잘 알고 있지만 이것이 압축 된 파일 크기와 어떻게 관련이 있는지 잘 모르겠습니다.

그렇다면 파일 포인터가 압축 파일로 얼마나 발전되는지 gzipstream에서 얻는 방법이 있습니까? 파일을 읽기 전에 가져올 수있는 현재 위치, GZ 파일 크기 만 있으면됩니다.

도움이 되었습니까?

해결책

계산 된 사이에 스트림을 꽂을 수 있습니다.

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

다른 팁

다음 코드를 살펴 보는 것이 좋습니다.

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

코드를 다시 방문했고 몇 가지 테스트를 수행했습니다. IMHO DARIN이 맞습니다. 그러나 ZIPPER 스트림의 헤더 (크기?) 만 읽고 결과 파일 크기를 찾을 수 있다고 생각합니다. (Winrar는 전체 zip 아카이브를 풀지 않고 압축 된 파일 크기가 무엇인지 알고 있습니다. 아카이브 헤더 에서이 정보를 읽습니다.) 결과 파일 크기를 찾으면이 코드를 사용하면 정확한 진행 상황을보고하는 데 도움이됩니다.

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

이게 도움이 되길 바란다.

압축 압축 진행을위한 프록시로서, 당신은 다음을 사용하여 기본 스트림에서 파일의 다운로드 진행에 대한 정보를 얻으려고 시도 할 수 있습니다.

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

또는

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

그것은에서 작동합니다 파일 스트림 그리고 그것은 작동해야합니다 getResponseStream () 그것을 구현하면 위치 속성 및 FTP 서버는 다운로드 된 파일 길이에 대한 정보를 반환합니다. http://msdn.microsoft.com/en-us/library/system.net.ftpwebresponse.contentlength(v=vs.110).aspx

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top