GzipStream을 사용한 컴퓨팅 진행 (BAR)
-
03-07-2019 - |
문제
느린 소스 (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