Created
September 15, 2021 13:34
-
-
Save marcussacana/6b400d72751a237e1d3c781713ce9b94 to your computer and use it in GitHub Desktop.
Random Access Stream (WIP)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ReadSeekableStream : Stream, IDisposable | |
{ | |
private readonly Stream Buffer; | |
private readonly Stream InputStream; | |
string TempFile = Path.GetTempFileName(); | |
public ReadSeekableStream(Stream Input) | |
{ | |
if (!Input.CanRead) | |
throw new Exception("Provided stream " + Input + " is not readable"); | |
InputStream = Input; | |
Buffer = new FileStream(TempFile, FileMode.OpenOrCreate, FileSystemRights.FullControl, FileShare.Read, 4096, FileOptions.RandomAccess, new FileSecurity()); | |
} | |
public override bool CanRead { get { return true; } } | |
public override bool CanSeek { get { return true; } } | |
public override int Read(byte[] buffer, int offset, int count) | |
{ | |
if (ReadPosition < InputPosition) { | |
Buffer.Position = ReadPosition; | |
int bReaded = Buffer.Read(buffer, offset, count); | |
ReadPosition += bReaded; | |
return bReaded; | |
} | |
if (ReadPosition > InputPosition) { | |
long Skiped = ReadPosition - InputPosition; | |
Buffer.Seek(0, SeekOrigin.End); | |
Skiped = Copy(InputStream, Buffer, Skiped); | |
InputPosition += Skiped; | |
} | |
if (ReadPosition != InputPosition) | |
throw new Exception("Bad Buffer Offset"); | |
int Readed = InputStream.Read(buffer, offset, count); | |
Buffer.Write(buffer, offset, Readed); | |
ReadPosition += Readed; | |
InputPosition += Readed; | |
return Readed; | |
} | |
public override long Seek(long offset, SeekOrigin origin) | |
{ | |
long AbsoluteOffset = origin switch | |
{ | |
SeekOrigin.Begin => offset, | |
SeekOrigin.Current => ReadPosition + offset, | |
SeekOrigin.End => InputStream.Length + offset, | |
_ => throw new Exception("Invalid Seek Origin") | |
}; | |
return ReadPosition = AbsoluteOffset; | |
} | |
long Copy(Stream From, Stream To, long Length) { | |
byte[] Buffer = new byte[1024 * 100]; | |
long TotalReaded = 0; | |
int Readed; | |
do | |
{ | |
long Reaming = Length - TotalReaded; | |
Readed = From.Read(Buffer, 0, Reaming > Buffer.Length ? Buffer.Length : (int)Reaming); | |
To.Write(Buffer, 0, Readed); | |
TotalReaded += Readed; | |
} while (Readed > 0); | |
To.Flush(); | |
return TotalReaded; | |
} | |
long ReadPosition = 0; | |
long InputPosition = 0; | |
public override long Position | |
{ | |
get { return ReadPosition; } | |
set { ReadPosition = value; } | |
} | |
public override void Close() | |
{ | |
Buffer?.Close(); | |
Buffer?.Dispose(); | |
if (File.Exists(TempFile)) | |
File.Delete(TempFile); | |
base.Close(); | |
} | |
protected override void Dispose(bool disposing) | |
{ | |
if (disposing) | |
InputStream.Close(); | |
Buffer?.Close(); | |
Buffer?.Dispose(); | |
if (File.Exists(TempFile)) | |
File.Delete(TempFile); | |
base.Dispose(disposing); | |
} | |
public override bool CanTimeout { get { return InputStream.CanTimeout; } } | |
public override bool CanWrite { get { return InputStream.CanWrite; } } | |
public override long Length { get { return InputStream.Length; } } | |
public override void SetLength(long value) { InputStream.SetLength(value); } | |
public override void Write(byte[] buffer, int offset, int count) { InputStream.Write(buffer, offset, count); } | |
public override void Flush() { InputStream.Flush(); } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment