C# Prepend 40 bytes onto stream - c#

I am trying to send a FileStream of a file.
But I now want to add 40 byte Checksum to the start.
How can I do this? Ive tried creating my own stream class to concatinate two streams.. And Ive looked at stream writers.
Surely they must be an easy way. Or an alternative way. And I DONT want to load the entire file into a byte array, appead to that and write that back to a stream.
public Stream getFile(String basePath, String path) {
return new FileStream(basePath + path, FileMode.Open, FileAccess.Read);
}

See MergeStream.cs. Here's how you can use it:
var mergeStream = new MergeStream(new MemoryStream(checksum), File.OpenRead(path));
return mergeStream;

byte[] checksum = new byte[40];
//...
FileStream oldFileStream = new FileStream(oldFile, FileMode.Open, FileAccess.Read);
FileStream newFileStream = new FileStream(newFile, FileMode.Create, FileAccess.Write);
using(oldFileStream)
using(newFileStream)
{
newFileStream.Write(checksum, 0, checksum.Length);
oldFileStream.CopyTo(newFileStream);
}
File.Copy(newFile, oldFile, overwrite : true);
If you don't want to use a temporary file, the only solution is to open the file in ReadWrite mode and use two alternating buffers:
private static void Swap<T>(ref T obj1, ref T obj2)
{
T tmp = obj1;
obj1 = obj2;
obj2 = tmp;
}
public static void PrependToFile(string filename, byte[] bytes)
{
FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite);
PrependToStream(stream, bytes);
}
public static void PrependToStream(Stream stream, byte[] bytes)
{
const int MAX_BUFFER_SIZE = 4096;
using(stream)
{
int bufferSize = Math.Max(MAX_BUFFER_SIZE, bytes.Length);
byte[] buffer1 = new byte[bufferSize];
byte[] buffer2 = new byte[bufferSize];
int readCount1;
int readCount2;
long totalLength = stream.Length + bytes.Length;
readCount1 = stream.Read(buffer1, 0, bytes.Length);
stream.Position = 0;
stream.Write(bytes, 0, bytes.Length);
int written = bytes.Length;
while (written < totalLength)
{
readCount2 = stream.Read(buffer2, 0, buffer2.Length);
stream.Position -= readCount2;
stream.Write(buffer1, 0, readCount1);
written += readCount1;
Swap(ref buffer1, ref buffer2);
Swap(ref readCount1, ref readCount2);
}
}
}

Related

C# data extracting from the file into byte array

Can anyone explain me about the following code what it is doing and
why it is substracting the size by 44.
public byte[] recorded_file = new byte[1000000];
public bool recorded_first_stream;
public int recorded_file_location;
public async void TestFile(object object_name)
{
string file_name = (string)object_name;
string full_file_name = System.IO.Path.Combine
(Properties.Settings.Default.wave_files_location, file_name);
if (File.Exists(full_file_name))
{
// WaveStream fileStream = new AudioFileReader(full_file_name);
recorded_first_stream = true;
FileStream fs = File.Open(full_file_name, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite);
recorded_file_location = (int)new System.IO.FileInfo(full_file_name).Length - 44;
BinaryReader wave_file = new BinaryReader(fs);
wave_file.BaseStream.Seek(44, SeekOrigin.Begin);
byte[] wave_bytes = wave_file.ReadBytes(1000000);
Buffer.BlockCopy(wave_bytes, 0, recorded_file, 0, wave_bytes.Length);
}

C# Split a file into two byte arrays

Because the maximum value of a byte array is 2GB, lets say i have a larger file and i need to convert it to a byte array. Since i can't hold the whole file, how should i convert it into two?
I tried:
long length = new System.IO.FileInfo(#"c:\a.mp4").Length;
int chunkSize = Convert.ToInt32(length / 2);
byte[] part2;
FileStream fileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
try
{
part2 = new byte[chunkSize]; // create buffer
fileStream.Read(part2, 0, chunkSize);
}
finally
{
fileStream.Close();
}
byte[] part3;
fileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
try
{
part3 = new byte[chunkSize]; // create buffer
fileStream.Read(part3, 5, (int)(length - (long)chunkSize));
}
finally
{
fileStream.Close();
}
but it's not working.
Any ideas?
You can use a StreamReader to read in file too large to read into a byte array
const int max = 1024*1024;
public void ReadALargeFile(string file, int start = 0)
{
FileStream fileStream = new FileStream(file, FileMode.Open,FileAccess.Read);
using (fileStream)
{
byte[] buffer = new byte[max];
fileStream.Seek(start, SeekOrigin.Begin);
int bytesRead = fileStream.Read(buffer, start, max);
while(bytesRead > 0)
{
DoSomething(buffer, bytesRead);
bytesRead = fileStream.Read(buffer, start, max);
}
}
}
If you are working with extremely large files, you should use MemoryMappedFile, which maps a physical file to a memory space:
using (var mmf = MemoryMappedFile.CreateFromFile(#"c:\path\to\big.file"))
{
using (var accessor = mmf.CreateViewAccessor())
{
byte myValue = accessor.ReadByte(someOffset);
accessor.Write((byte)someValue);
}
}
See also: MemoryMappedViewAccessor
You can also read/write chunks of the file with the different methods in MemoryMappedViewAccessor.
This was my solution:
byte[] part1;
byte[] part2;
bool odd = false;
int chunkSize = Convert.ToInt32(length/2);
if (length % 2 == 0)
{
part1 = new byte[chunkSize];
part2 = new byte[chunkSize];
}
else
{
part1 = new byte[chunkSize];
part2 = new byte[chunkSize + 1];
odd = true;
}
FileStream fileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
using (fileStream)
{
fileStream.Seek(0, SeekOrigin.Begin);
int bytesRead = fileStream.Read(part1, 0, chunkSize);
if (odd)
{
bytesRead = fileStream.Read(part2, 0, chunkSize + 1);
}
else
{
bytesRead = fileStream.Read(part2, 0, chunkSize);
}
}

C# - Compress byte[]

I receive a zip file base64 string, convert to byte[], open in memory, modify content, and then 'compress' the new byte[] to base64 string again.
My problem, I don't know how to 'compress' the new byte[] to zip format.
public string ModifyZipContent(string base64) {
ZipPackage zipPackage = null;
MemoryStream memoryStream = null;
long lenght;
byte[] data = Convert.FromBase64String(base64);
byte[] buffer;
byte[] newData;
int arrayOffset = 0;
memoryStream = new MemoryStream();
memoryStream.Write(data, 0, data.Length);
zipPackage = (ZipPackage)Package.Open(memoryStream, FileMode.Open);
PackagePartCollection zipParts = zipPackage.GetParts();
// this is awful
foreach(ZipPackagePart zipPart in zipParts) {
using(Stream stream = zipPart.GetStream()) {
arrayOffset += (int)stream.Length;
}
}
newData = new byte[arrayOffset];
// end
arrayOffset = 0;
foreach(ZipPackagePart zipPart in zipParts) {
using(Stream stream = zipPart.GetStream()) {
lenght = stream.Length;
buffer = new byte[lenght];
stream.Read(buffer, 0, (int)lenght);
Buffer.BlockCopy(buffer, 0, newData, arrayOffset, buffer.Length);
arrayOffset += buffer.Length;
}
}
return Convert.ToBase64String(newData);
}
I haven't fully tested this, but something along these lines should work...
// Requires System.IO.Compression using statement.
byte[] bytes = new byte[256]; // Your byte[] would be here instead of this empty one.
using (var zipFile = ZipFile.Open("C:/ZipFile.zip", ZipArchiveMode.Update))
{
var entry = zipFile.CreateEntry("YourEntryPathHere");
using (var stream = entry.Open())
{
stream.Write(bytes, 0, bytes.Length);
}
}

uncompressed file is bigger than original file in GZIP

i'm using the following function to compress(thanks to http://www.dotnetperls.com/):
public static void CompressStringToFile(string fileName, string value)
{
// A.
// Write string to temporary file.
string temp = Path.GetTempFileName();
File.WriteAllText(temp, value);
// B.
// Read file into byte array buffer.
byte[] b;
using (FileStream f = new FileStream(temp, FileMode.Open))
{
b = new byte[f.Length];
f.Read(b, 0, (int)f.Length);
}
// C.
// Use GZipStream to write compressed bytes to target file.
using (FileStream f2 = new FileStream(fileName, FileMode.Create))
using (GZipStream gz = new GZipStream(f2, CompressionMode.Compress, false))
{
gz.Write(b, 0, b.Length);
}
}
and for decompress:
static byte[] Decompress(byte[] gzip)
{
// Create a GZIP stream with decompression mode.
// ... Then create a buffer and write into while reading from the GZIP stream.
using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
const int size = 4096;
byte[] buffer = new byte[size];
using (MemoryStream memory = new MemoryStream())
{
int count = 0;
do
{
count = stream.Read(buffer, 0, size);
if (count > 0)
{
memory.Write(buffer, 0, count);
}
}
while (count > 0);
return memory.ToArray();
}
}
}
so my goal is actually compress log files and than to decompress them in memory and compare the uncompressed file to the original file in order to check that the compression succeeded and i'm able to open the compressed file successfuly.
the problem is that the uncompressed file is most of the time bigger than the original file and my compare check is failing altough the compression probably succeeded.
any idea why ?
btw here how i compare the uncompressed file to the original file:
static bool FileEquals(byte[] file1, byte[] file2)
{
if (file1.Length == file2.Length)
{
for (int i = 0; i < file1.Length; i++)
{
if (file1[i] != file2[i])
{
return false;
}
}
return true;
}
return false;
}
Try this method to compress a file:
public static byte[] Compress(byte[] raw)
{
using (MemoryStream memory = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(memory,
CompressionMode.Compress, true))
{
gzip.Write(raw, 0, raw.Length);
}
return memory.ToArray();
}
}
}
And this to decompress :
static byte[] Decompress(byte[] gzip)
{
// Create a GZIP stream with decompression mode.
// ... Then create a buffer and write into while reading from the GZIP stream.
using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
const int size = 4096;
byte[] buffer = new byte[size];
using (MemoryStream memory = new MemoryStream())
{
int count = 0;
do
{
count = stream.Read(buffer, 0, size);
if (count > 0)
{
memory.Write(buffer, 0, count);
}
}
while (count > 0);
return memory.ToArray();
}
}
}
}
Tell me if it worked.
Goodluck.
Think you'd be better off with the simplest API call, try Stream.CopyTo(). I can't find the error in your code. If I was working on it, I'd probably make sure everything is getting flushed properly.. can't recall if GZipStream is going to flush its output to FileStream when the using block closes.. but then you are also saying that the final file is larger, not smaller.
Anyhow, best policy in my experience.. don't rewrite gotcha prone code when you don't need to. At least you tested it ;)

How to get a MemoryStream from a Stream in .NET?

I have the following constructor method which opens a MemoryStream from a file path:
MemoryStream _ms;
public MyClass(string filePath)
{
byte[] docBytes = File.ReadAllBytes(filePath);
_ms = new MemoryStream();
_ms.Write(docBytes, 0, docBytes.Length);
}
I need to change this to accept a Stream instead of a file path. Whats the easiest/most efficient way to get a MemoryStream from the Stream object?
In .NET 4, you can use Stream.CopyTo to copy a stream, instead of the home-brew methods listed in the other answers.
MemoryStream _ms;
public MyClass(Stream sourceStream)
_ms = new MemoryStream();
sourceStream.CopyTo(_ms);
}
Use this:
var memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
This will convert Stream to MemoryStream.
If you're modifying your class to accept a Stream instead of a filename, don't bother converting to a MemoryStream. Let the underlying Stream handle the operations:
public class MyClass
{
Stream _s;
public MyClass(Stream s) { _s = s; }
}
But if you really need a MemoryStream for internal operations, you'll have to copy the data out of the source Stream into the MemoryStream:
public MyClass(Stream stream)
{
_ms = new MemoryStream();
CopyStream(stream, _ms);
}
// Merged From linked CopyStream below and Jon Skeet's ReadFully example
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[16*1024];
int read;
while((read = input.Read (buffer, 0, buffer.Length)) > 0)
{
output.Write (buffer, 0, read);
}
}
You can simply do:
var ms = new MemoryStream(File.ReadAllBytes(filePath));
Stream position is 0 and ready to use.
You will have to read in all the data from the Stream object into a byte[] buffer and then pass that into the MemoryStream via its constructor. It may be better to be more specific about the type of stream object you are using. Stream is very generic and may not implement the Length attribute, which is rather useful when reading in data.
Here's some code for you:
public MyClass(Stream inputStream) {
byte[] inputBuffer = new byte[inputStream.Length];
inputStream.Read(inputBuffer, 0, inputBuffer.Length);
_ms = new MemoryStream(inputBuffer);
}
If the Stream object doesn't implement the Length attribute, you will have to implement something like this:
public MyClass(Stream inputStream) {
MemoryStream outputStream = new MemoryStream();
byte[] inputBuffer = new byte[65535];
int readAmount;
while((readAmount = inputStream.Read(inputBuffer, 0, inputBuffer.Length)) > 0)
outputStream.Write(inputBuffer, 0, readAmount);
_ms = outputStream;
}
I use this combination of extension methods:
public static Stream Copy(this Stream source)
{
if (source == null)
return null;
long originalPosition = -1;
if (source.CanSeek)
originalPosition = source.Position;
MemoryStream ms = new MemoryStream();
try
{
Copy(source, ms);
if (originalPosition > -1)
ms.Seek(originalPosition, SeekOrigin.Begin);
else
ms.Seek(0, SeekOrigin.Begin);
return ms;
}
catch
{
ms.Dispose();
throw;
}
}
public static void Copy(this Stream source, Stream target)
{
if (source == null)
throw new ArgumentNullException("source");
if (target == null)
throw new ArgumentNullException("target");
long originalSourcePosition = -1;
int count = 0;
byte[] buffer = new byte[0x1000];
if (source.CanSeek)
{
originalSourcePosition = source.Position;
source.Seek(0, SeekOrigin.Begin);
}
while ((count = source.Read(buffer, 0, buffer.Length)) > 0)
target.Write(buffer, 0, count);
if (originalSourcePosition > -1)
{
source.Seek(originalSourcePosition, SeekOrigin.Begin);
}
}
How do I copy the contents of one stream to another?
see that. accept a stream and copy to memory. you should not use .Length for just Stream because it is not necessarily implemented in every concrete Stream.
public static void Do(Stream in)
{
_ms = new MemoryStream();
byte[] buffer = new byte[65536];
while ((int read = input.Read(buffer, 0, buffer.Length))>=0)
_ms.Write (buffer, 0, read);
}
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}

Categories