I am building a XmlDocument in memory (I am not writing it to disk). I need to be able to create a zip archive that would contain the Xml file and then get the zip archive as byte array (all of this without actually writing/creating anything on the hard-disk). Is this possible?
I should mention that I am trying to do this in C#.
var buffer = new MemoryStream();
using (buffer)
using (var zip = new ZipArchive(buffer, ZipArchiveMode.Create) )
{
var entry = zip.CreateEntry("content.xml", CompressionLevel.Optimal);
using (var stream = entry.Open())
{
xmlDoc.Save(stream);
}
}
var bytes = buffer.ToArray();
Related
In C# I create zip archive with some files:
using (MemoryStream ms = new MemoryStream())
{
using (ZipStorer zip = ZipStorer.Create(ms, "comment"))
{
zip.EncodeUTF8 = true;
foreach (FileInfo logFile in logFiles)
{
zip.AddFile(ZipStorer.Compression.Deflate, logFile.FullName, logFile.Name, "");
}
}
this.logger.log("memory stream to array");
zipBytesArr = ms.ToArray();
}
It works, because when I persist zip archive on server with C# - I can open it.
File.WriteAllBytes("C:\\test.zip", zipBytesArr);
Now I send it as bytes array zipBytesArr in POST request, I create object with field type byte[], than serialise it to JSON and send.
MyObject myObject = new MyObject()
{
// .. some fields
ZipFileBytesArr = ZipFileBytesArr
};
var json = JsonConvert.SerializeObject(myObject);
Now I want to get it in Python 3 (flask), I got some long string and I want to create zip archive. My question is: how to achieve this?
I tried something like this:
bytes_as_str = "UEsDBBQAAAgIACyrWk4qVSmD0gYAAA4WAAAYAAAAMjAxOTAyMjZfb3BlbnZ...."
bytes_as_bytes = bytes_as_str.encode(encoding="utf-8")
file = zipfile.ZipFile(io.BytesIO(bytes_as_bytes))
and it does not work, I got an error:
zipfile.BadZipFile: File is not a zip file
Scenario
I have a object that I convert to a flat CSV and then compress and upload to a filestore.
I could easily do this by following the below steps.
Convert object to CSV file.
Compress file
Upload file.
However
I do not want the penalty that comes with touching physical storage so would like to do all this in memory.
Current Incorrect Implementation
Convert object to CSV byte array
Compress byte array
Upload byte array to file store
Problem
What i'm essentially doing is compressing a byte array and uploading that. which is obviously wrong. (Because when the compressed Gzip file is uncompressed, it contains a byte array of the csv and not the actual csv itself.)
Is it possible to create a file like "file.csv" in memory and then compress that in memory, instead of compressing a byte array?
The problem I'm having is it would seem I can only name the file and specify its extension when saving to a physical location.
Code Example of Current Implementation
public byte[] Example(IEnumerable<object> data)
{
// Convert Object to CSV and write to byte array.
byte[] bytes = null;
using (var ms = new MemoryStream())
{
TextWriter writer = new StreamWriter(ms);
var csv = new CsvWriter(writer);
csv.WriteRecords(data);
writer.Flush();
ms.Position = 0;
bytes = ms.ToArray();
}
//Compress byte array
using (var compressedStream = new MemoryStream(bytes))
using (var resultStream = new MemoryStream())
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
{
zipStream.CopyTo(resultStream);
zipStream.Close();
var gzipByteArray = resultStream.ToArray();
//Upload to AzureStorage
new AzureHelper().UploadFromByteArray(gzipByteArray, 0, gzipByteArray.Length);
}
}
Wrap the Stream you use for the upload in a GZipStream, write your CSV to that, and the then you'll have uploaded the compressed CSV.
I need to convert a byte array into an excel file using C# to upload it in Sharepoint.
The following code read an input file from client as a byte array:
public object UploadFile(HttpPostedFile file)
{
byte[] fileData = null;
using (var binaryReader = new BinaryReader(file.InputStream))
{
fileData = binaryReader.ReadBytes(imageFile.ContentLength);
// convert fileData to excel
}
}
How can I do it?
It sounds like you're just after File.WriteAllBytes(path, contents). However, if the input file could be large, you may be better off using the Stream API:
using(var destination = File.Create(path)) {
file.InputStream.CopyTo(destination);
}
Edit: it looks like HttpPostedFile has a SaveAs method, so just:
file.SaveAs(path);
How can I decompress (.zip) files without extracting to a new location in the .net framework? Specifically, I'm trying to read a filename.csv.zip into a DataTable.
I'm aware of .extractToDirectory (which is within ZipArchive) but I just want to extract it into an object in c# and I would like to not create a new file.
Hoping to be able to do this w/o third party libraries, but I'll take what I can get.
May be some bugs because I never tested this, but here you go:
List<byte[]> urmom = new List<byte[]>();
using (ZipArchive archive = ZipFile.OpenRead(zipPath))
foreach (ZipArchiveEntry entry in archive.Entries)
using (StreamReader r = new StreamReader(entry.Open()))
urmom.Add(r.ReadToEnd(entry));
Basically you use the ZipArchive's openread class to iterate through each entry. At this point, you can use the streamreader to read each entry. From there you can create a file from the stream and even read the filename if you want to. My code doesn't do this, a bit of laziness on my part.
Keep in mind that a compressed stream might contain multiple files. To resolve this is required to iterate through all entries of zip file in order to retrieve them and treat separately.
The sample bellow converts a sequence of bytes in a list of string where each one is the context of the files included in zipped folder:
public static IEnumerable<string> DecompressToEntriesTextContext(byte[] input)
{
var zipEntriesContext = new List<string>();
using (var compressedStream = new MemoryStream(input))
using (var zip = new ZipArchive(compressedStream, ZipArchiveMode.Read))
{
foreach(var entry in zip.Entries)
{
using (var entryStream = entry.Open())
using (var memoryEntryStream = new MemoryStream())
using (var reader = new StreamReader(memoryEntryStream))
{
entryStream.CopyTo(memoryEntryStream);
memoryEntryStream.Position = 0;
zipEntriesContext.Add(reader.ReadToEnd());
}
}
}
return zipEntriesContext;
}
I want to convert mp3 files to WAV. In DirectX.DirectSound the secondary buffer is supporting only WAV. I am converting the files using naudio and this is working fine.
using (Mp3FileReader reader = new Mp3FileReader(mp3File))
{
WaveFileWriter.CreateWaveFile(outputFile, reader);
}
The problem is that I can't save the files on disk so I have to use them with stream.
Mp3FileReader mp3reader = new Mp3FileReader(filenamePathMp3);
var stream=WaveFormatConversionStream.CreatePcmStream(mp3reader);
which throws an exception Value does not fall within the expected range. How Can I make a stream with the audio converted to WAV or Raw audio for the secondaryBuffer without writing on disk?
Thank you in advance,
WaveFileWriter can write to a Stream instead of a file so you can just pass in a MemoryStream. Also, Mp3FileReader.Read already returns PCM so you could read out into a byte[] and then insert that into your memory stream if you prefer.
I've achieved to convert MP3 to WAV without writing it to the disk by using MemoryStream and WaveFileWriter.WriteWavFileToStream
You can also set up sampleRate bitrate and channel using RawSourceWaveStream
public static byte[] ConvertMp3ToWav(byte[] mp3File)
{
using (var retMs = new MemoryStream())
using (var ms = new MemoryStream(mp3File))
using (Mp3FileReader reader = new Mp3FileReader(ms))
{
var rs = new RawSourceWaveStream(reader, new WaveFormat(16000, 1));
using (WaveStream pcmStream = WaveFormatConversionStream.CreatePcmStream(rs))
{
WaveFileWriter.WriteWavFileToStream(retMs,pcmStream);
return retMs.ToArray();
}
}
}