Writing a stream to a File and to memory - c#

I'm trying to read an EmbeddedResource (a default config file) and write it to a File. After that I should read the file and to make things easier I decided to do that in a single step.
private string CreateDefaultFile()
{
using (var stream = Shelter.Assembly.GetManifestResourceStream($#"Mod.Resources.Config.{_file}"))
{
if (stream == null)
throw new NullReferenceException(); //TODO
using (var ms = new MemoryStream())
{
using (var fs = new FileStream(Shelter.ModDirectory + _file, FileMode.Create, FileAccess.Write, FileShare.Read))
{
byte[] buffer = new byte[512];
int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, bytesRead);
fs.Write(buffer, 0, bytesRead);
}
fs.Flush();
ms.Flush();
return Encoding.UTF8.GetString(ms.ToArray());
}
}
}
}
This does create the file but the return value doesn't seem to work as it should. The content seems correct but JSON.Net cannot parse it with this error:
JsonReaderException: Unexpected character encountered while parsing value: . Path '', line 0, position 0.. Using File.ReadAllText(...) instead of Encoding.UTF8.GetString(ms.ToArray()) seems to work so I'm guessing this is a problem with how I load the stream into a string.
Also the chunking part is not needed as the file is small in size, I've read in multiple places that is better use so I'd prefer it.
(Targeting .NET Framework 3.5)

Thanks to dbc comment and Tergiver answer I fixed the issue.
The code:
private string CreateDefaultFile()
{
using (var stream = Shelter.Assembly.GetManifestResourceStream($#"Mod.Resources.Config.{_file}"))
{
if (stream == null)
throw new NullReferenceException(); //TODO
using (var ms = new MemoryStream())
{
using (var fs = File.Open(Shelter.ModDirectory + _file, FileMode.Create, FileAccess.Write, FileShare.Read))
{
byte[] buffer = new byte[512];
int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, bytesRead);
fs.Write(buffer, 0, bytesRead);
}
fs.Flush();
ms.Flush();
byte[] content = ms.ToArray();
if (content.Length >= 3 && content[0] == 0xEF && content[1] == 0xBB && content[2] == 0xBF)
return Encoding.UTF8.GetString(content, 3, content.Length - 3);
return Encoding.UTF8.GetString(content);
}
}
}
}

Related

Zip file is getting corrupted after downloading from server in C#

request = MakeConnection(uri, WebRequestMethods.Ftp.DownloadFile, username, password);
response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
//This part of the code is used to write the read content from the server
using (StreamReader responseReader = new StreamReader(responseStream))
{
using (var destinationStream = new FileStream(toFilenameToWrite, FileMode.Create))
{
byte[] fileContents = Encoding.UTF8.GetBytes(responseReader.ReadToEnd());
destinationStream.Write(fileContents, 0, fileContents.Length);
}
}
//This part of the code is used to write the read content from the server
using (var destinationStream = new FileStream(toFilenameToWrite, FileMode.Create))
{
long length = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[2048];
readCount = responseStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
destinationStream.Write(buffer, 0, readCount);
readCount = responseStream.Read(buffer, 0, bufferSize);
}
}
The former ones writes the content to the file but when I try to open the file it says it is corrupted. But the later one does the job perfectly when downloading zip files. Is there any specific reason why the former code doesn't work for zip files as it works perfectly for text files?
byte[] fileContents = Encoding.UTF8.GetBytes(responseReader.ReadToEnd());
You try to interpret a binary PDF file as an UTF-8 text. That just cannot work.
For a correct code, see Upload and download a binary file to/from FTP server in C#/.NET.
Use BinaryWriter and pass it FileStream.
//This part of the code is used to write the read content from the server
using (var destinationStream = new BinaryWriter(new FileStream(toFilenameToWrite, FileMode.Create)))
{
long length = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[2048];
readCount = responseStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
destinationStream.Write(buffer, 0, readCount);
readCount = responseStream.Read(buffer, 0, bufferSize);
}
}
here is my solution that worked for me
C#
public IActionResult GetZip([FromBody] List<DocumentAndSourceDto> documents)
{
List<Document> listOfDocuments = new List<Document>();
foreach (DocumentAndSourceDto doc in documents)
listOfDocuments.Add(_documentService.GetDocumentWithServerPath(doc.Id));
using (var ms = new MemoryStream())
{
using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
foreach (var attachment in listOfDocuments)
{
var entry = zipArchive.CreateEntry(attachment.FileName);
using (var fileStream = new FileStream(attachment.FilePath, FileMode.Open))
using (var entryStream = entry.Open())
{
fileStream.CopyTo(entryStream);
}
}
}
ms.Position = 0;
return File(ms.ToArray(), "application/zip");
}
throw new ErrorException("Can't zip files");
}
don't miss the ms.Position = 0; here

Extract a bytearray variable using C# DotNetZip

I have a C# function that receives a compressed ByteArray as a parameter.
I need to EXTRACT this byteArray and send the resulting uncompressed byteArray to another function.
I need help extracting zipBytes to unzippedBytes please see below PSEUDO CODE:
SOLUTION using Zlib.net!
byte[] receiveZipByte (byte[] zipBytes)
{
MemoryStream oInStream = new MemoryStream(pZFileData);
ZInputStream oZInstream = new ZInputStream(oInStream);
MemoryStream oOutStream = new MemoryStream();
byte[] buffer = new byte[2000];
int len;
while ((len = oZInstream.read(buffer, 0, 2000)) > 0)
{
oOutStream.Write(buffer, 0, len);
}
byte[] pFileData = oOutStream.ToArray();
oZInstream.Close();
oOutStream.Close();
return unzippedBytes;
}
If what you're trying to do is decompress data that has been compressed using zlib, I would suggest using the ZLib.NET library: http://www.componentace.com/zlib_.NET.htm
It would depend on what you want to do with the data; but, here's an example of using a Stream with DotNetZip:
using (var input = new ZipInputStream(new MemoryStream(zipBytes)))
{
ZipEntry e;
while ((e = input.GetNextEntry()) != null)
{
if (e.IsDirectory) continue;
using (var output = File.Open(e.FileName, FileMode.Create, FileAccess.ReadWrite))
{
while ((n = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, n);
}
}
}
}

Download to file and save to byte array

I am trying to download a file to my computer and in the same time save it to Byte Array:
try
{
var req = (HttpWebRequest)HttpWebRequest.Create(url);
var fileStream = new FileStream(filePath,
FileMode.Create, FileAccess.Write, FileShare.Write);
using (var resp = req.GetResponse())
{
using (var stream = resp.GetResponseStream())
{
byte[] buffer = new byte[0x10000];
int len;
while ((len = stream.Read(buffer, 0, buffer.Length)) > 0)
{
//Do with the content whatever you want
// ***YOUR CODE***
MemoryStream memoryStream = new MemoryStream();
if (len > 0)
{
memoryStream.Write(buffer, 0, len);
len = stream.Read(buffer, 0, buffer.Length);
}
file = memoryStream.ToArray();
fileStream.Write(buffer, 0, len);
}
}
}
fileStream.Close();
}
catch (Exception exc) { }
And i noticed that it's not download all the file with this.
I wan to do it because i want to download a file and in the same time work with it.
Any idea why this problem happen?
There is a much easier way to get the file bytes by using the System.Net.WebClient.WebClient():
private static byte[] DownloadFile(string absoluteUrl)
{
using (var client = new System.Net.WebClient())
{
return client.DownloadData(absoluteUrl);
}
}
Usage:
var bytes = DownloadFile(absoluteUrl);
The problem looks to be double-reading - you are putting different things into the memory-stream / file-stream - it should be more like:
// declare file/memory stream here
while ((len = stream.Read(buffer, 0, buffer.Length)) > 0)
{
memoryStream.Write(buffer, 0, len);
fileStream.Write(buffer, 0, len);
// if you need to process "len" bytes, do it here
}
You might be able to lose "memoryStream" completely if you are processing the "len" bytes immediately. If it fits in-memory, it may be easier to just use WebClient.DownloadData and then File.WriteAllBytes.

How to overwrite an existing image with c#?

To save an image I use the following code:
string filenamewithpath =
System.Web.HttpContext.Current.Server.MapPath(
#"~/userimages/" + incID + ".jpg");
System.IO.File.WriteAllBytes(filenamewithpath, Util.ReadFully(image));
public class Util
{
public static byte[] ReadFully(Stream stream)
{
byte[] buffer = new byte[32768];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
}
The above works for saving the image with an ID. When updating, I need to overwrite the existing image, and would need some advice on how to do this.
If you just need to get rid of the old image file before writing the new one, why not just call
if (System.IO.File.Exists(filenamewithpath)
{
System.IO.File.Delete(filenamewithpath);
}
Although, the description of System.IO.File.WriteAllBytes already says that "if the file exists, it is overwritten".
System.IO.File.WriteAllBytes(filenamewithpath, Util.ReadFully(image));
replace this line with:
using (FileStream fs = new FileStream(filenamewithpath, FileMode.OpenOrCreate))
{
var bytes=Util.ReadFully(image);
fs.Write(bytes, 0, bytes.Length);
}

compressing and decomressing in .net endsup with an decompressed array of zero's

I'm trying to compress and decompress a memory stream to send it over an tcp connection.
In the following code snap I do do the decompressing right after compressing to get it working first.
What ever I do I end up with a devompressed buffer wit all zero's and in the line
int read = Decompress.Read(buffie, 0, buffie.Length);
it seems that 0 bytes are read.
Does anyone has a clue what is wrong?
bytesRead = ms.Read(buf, 0, i);
MemoryStream partialMs = new MemoryStream();
GZipStream gZip = new GZipStream(partialMs, CompressionMode.Compress);
gZip.Write(buf, 0, buf.Length);
partialMs.Position = 0;
byte[] compressedBuf = new byte[partialMs.Length];
partialMs.Read(compressedBuf, 0, (int)partialMs.Length);
partialMs.Close();
byte[] gzBuffer = new byte[compressedBuf.Length + 4];
System.Buffer.BlockCopy(compressedBuf, 0, gzBuffer, 4, compressedBuf.Length);
System.Buffer.BlockCopy(BitConverter.GetBytes(buf.Length), 0, gzBuffer, 0, 4);
using (MemoryStream mems = new MemoryStream())
{
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
byte[] buffie = new byte[msgLength];
mems.Write(gzBuffer, 4, gzBuffer.Length - 4);
mems.Flush();
mems.Position = 0;
using (GZipStream Decompress = new GZipStream(mems, CompressionMode.Decompress, true))
{
int read = Decompress.Read(buffie, 0, buffie.Length);
Decompress.Close();
}
}
Your implementation could use some work. there seems to be some confusion as to which streams should be used where. here is a working example to get you started..
see user content at the bottom of this MSDN page
var original = new byte[65535];
var compressed = GZipTest.Compress(original);
var decompressed = GZipTest.Decompress(compressed);
using System.IO;
using System.IO.Compression;
public class GZipTest
{
public static byte[] Compress(byte[] uncompressedBuffer)
{
using (var ms = new MemoryStream())
{
using (var gzip = new GZipStream(ms, CompressionMode.Compress, true))
{
gzip.Write(uncompressedBuffer, 0, uncompressedBuffer.Length);
}
byte[] compressedBuffer = ms.ToArray();
return compressedBuffer;
}
}
public static byte[] Decompress(byte[] compressedBuffer)
{
using (var gzip = new GZipStream(new MemoryStream(compressedBuffer), CompressionMode.Decompress))
{
byte[] uncompressedBuffer = ReadAllBytes(gzip);
return uncompressedBuffer;
}
}
private static byte[] ReadAllBytes(Stream stream)
{
var buffer = new byte[4096];
using (var ms = new MemoryStream())
{
int bytesRead = 0;
do
{
bytesRead = stream.Read(buffer, 0, buffer.Length);
if (bytesRead > 0)
{
ms.Write(buffer, 0, bytesRead);
}
} while (bytesRead > 0);
return ms.ToArray();
}
}
}
You're not closing the GzipStream you're writing to, so it's probably all buffered. I suggest you close it when you're done writing your data.
By the way, you can get the data out of a MemoryStream much more easily than your current code: use MemoryStream.ToArray.

Categories