C#流OffsetStream.cs扩展.net压缩库SharpCompress

44 篇文章 0 订阅
16 篇文章 0 订阅
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace SharpCompress.IO
{
    /// <summary>
    ///  this is a read-only stream, maybe we should be a StreamReader
    ///  warning: the originalStream cann't chang length when using this stream
    /// </summary>
    public class OffsetStream : System.IO.Stream
    {
        Stream _originalStream;
        long _os_originalOffset;
        long _of_length;
        long _os_originalCurrentPos;
        /// <summary>
        /// 只适合读写 关联流的中指定偏移位置以及长度的一部分数据,
        /// 当前流关闭不会影响关联的流
        /// </summary>
        /// <param name="originalStream"></param>
        /// <param name="offset">原始流的偏移位置(立即设置原始流的postion=offset)</param>
        /// <param name="length">在原始流中的长度</param>
        public OffsetStream(Stream originalStream, long offset, long length) {
            if (originalStream == null) {
                throw new Exception("null source stream for new OffsetStream()");
            }
            this._originalStream = originalStream;
            this._os_originalOffset = offset;
            this._of_length = length;
            this.Position = 0; // reset to beginning (?)
            System.Diagnostics.Debug.Assert(length >= 0 && length <= (originalStream.Length - offset));
            if (length < 0 || length > (originalStream.Length - offset)) {
                throw new Exception("out length with offsetStream.");
            }
        }
        /// <summary>
        /// 只适合读写 关联流的中指定偏移位置以及长度的一部分数据
        /// </summary>
        /// <param name="originalStream"></param>
        /// <param name="offset"></param>
        public OffsetStream(Stream originalStream, long offset)
            : this(originalStream, offset, originalStream.Length - offset) { }

        public override bool CanRead { get { return _originalStream.CanRead; } }
        public override bool CanSeek { get { return _originalStream.CanSeek; } }
        public override bool CanWrite { get { return _originalStream.CanWrite; } }
        public override bool CanTimeout {
            get { return _originalStream.CanTimeout; }
        }
        public override int ReadTimeout {
            get { return _originalStream.ReadTimeout; }
            set { _originalStream.ReadTimeout = value; }
        }

        public override int WriteTimeout {
            get { return _originalStream.WriteTimeout; }
            set { _originalStream.WriteTimeout = value; }
        }

        public override void Flush() { _originalStream.Flush(); }
        /// <summary>
        /// 注意:原始关联流的长度不可减少,否则会造成流位置超出长度的异常
        /// </summary>
        public override long Length {
            get {
                //return  _os_length;
                long newlen = _originalStream.Length - _os_originalOffset;
                if (newlen < _of_length) {
                    throw new Exception("the offset length not allowed on  Less than  origibal input stream length! ");
                }
                return newlen;
            }
        }

        public override long Position {
            get {
                _os_originalCurrentPos = _originalStream.Position;
                long newpos = _os_originalCurrentPos - _os_originalOffset;
                return newpos;
            }
            set {
                _os_originalCurrentPos = _os_originalOffset + value;
                _originalStream.Position = _os_originalCurrentPos;
            }
        }
        /// <summary>
        /// 会修改关联流的长度,谨慎使用
        /// </summary>
        /// <param name="value"></param>
        public override void SetLength(long value) {
            //
            //if (value < 0L) throw new Exception("setlength not allowed on Less than  OffsetStream");
            if ((value - _os_originalOffset) < _of_length) throw new Exception("setlength not allowed on Less than  OffsetStream");
            long newlen = value + _os_originalOffset;
            _originalStream.SetLength(newlen);
        }
        public override long Seek(long offset, SeekOrigin origin) {
            long new_offset = _originalStream.Position + offset; // SeekOrigin.Current

            switch (origin) {
                case SeekOrigin.Begin:
                    new_offset = _os_originalOffset + offset;
                    goto case SeekOrigin.Current;
                case SeekOrigin.End:
                    if (offset > 0) {
                        throw new Exception("OffsetStream.Seek(offset,SeekOrigin.End) outside offset stream limits");
                    }
                    new_offset = _os_originalOffset + _of_length + offset;
                    goto case SeekOrigin.Current;
                case SeekOrigin.Current:
                    if ((new_offset < _os_originalOffset) || (new_offset >= (_os_originalOffset + _of_length))) {
                        throw new Exception(
                            "OffsetStream.Seek() outside offset stream limits" +
                            String.Format(", parms({0},{1})", offset, origin.ToString()) +
                            String.Format(", new_offset({0}) os_offset({1}) os_length({2})", new_offset, _os_originalOffset, _of_length));
                    }
                    return _originalStream.Seek(new_offset, SeekOrigin.Begin) - _os_originalOffset;
                default:
                    throw new Exception("unknown SeekOrigin value" + origin.ToString());
            }
        }

        public override int Read(byte[] buffer, int offset, int count) {
            // TODO: we should rangecheck our current seekpointer against our offsets and count
            int num_read = _originalStream.Read(buffer, offset, count);
            return num_read;
        }
        /// <summary>
        /// 指定长度内的数据写入
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public override void Write(byte[] buffer, int offset, int count) {
            _originalStream.Write(buffer, offset, count);
        }

        public bool KeepStreamsOpen { get; private set; }
        protected override void Dispose(bool disposing) {           
            base.Dispose(disposing);
            if (disposing && !KeepStreamsOpen) {
                _originalStream.Dispose();
            }
        }
    }
}

string SCRATCH_FILES_PATH = "ziptest";
            string scratchPath = "ziptest.zip";

             using (var archive = ZipArchive.Create())
             {
                 archive.AddAllFromDirectory(SCRATCH_FILES_PATH);
                 archive.SaveTo(scratchPath, CompressionType.Deflate);
                 using (FileStream fs = new FileStream("ziphead.zip", FileMode.OpenOrCreate, FileAccess.ReadWrite)) {
                     MyHead mh = new MyHead();
                     byte[] headData = mh.Create();
                     fs.Write(headData, 0, headData.Length);
                     //
                     SharpCompress.IO.OffsetStream ofs = new IO.OffsetStream(fs, fs.Position);
                     archive.SaveTo(ofs, CompressionType.Deflate);
                 }

             }

  //
            //read my zip file with head
            //
             using (FileStream fs = new FileStream("mypack.data.zip", FileMode.Open, FileAccess.Read, FileShare.Read)) {
                 byte[] buf = new byte[1024];
                 int offset=fs.Read(buf, 0, buf.Length);
                 System.Diagnostics.Debug.Assert(offset==1024);
                 //fs.Position = 0L;
                 SharpCompress.IO.OffsetStream substream = new SharpCompress.IO.OffsetStream(fs,offset);
                 ZipArchive zip = ZipArchive.Open(substream, Options.KeepStreamsOpen);//cann't read
                 //ZipArchive zip = ZipArchive.Open(fs, Options.None); //will throw exption
                 //ZipArchive zip = ZipArchive.Open(fs, Options.KeepStreamsOpen);//cann't read
                 
                 foreach (ZipArchiveEntry zf in zip.Entries) {
                     Console.WriteLine(zf.Key);
                     //bug:the will not none in zipfile
                 }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rains卍Soft

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值