Hi I am trying to make working this piece of code, after the copy of the word file template into a memory stream, read it and replace some text, I would convert the stream writer to byte array which will be used to download the result. Thanks in advance
public byte[] GetWordFile()
{
try
{
string sourceFile = Path.Combine("C:/[...]/somefile.docx");
using (MemoryStream inStream = new MemoryStream())
{
using (Stream fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read))
{
fs.CopyTo(inStream);
}
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(inStream, true))
{
string docText = null;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
docText = docText.Replace("numpol", "HAHAHHAHA");
using (MemoryStream outStream = new MemoryStream())
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
sw.Flush();
sw.BaseStream.CopyTo(outStream);
outStream.Position = 0;
return outStream.ToArray();
}
}
}
}
catch (Exception ex)
{
///...
}
}
Related
How do I convert from a gzip compressed file to Zstandard? Here is my attempt:
using Zstandard.Net;
public static void ConvertToZstd(string path)
{
byte[] compressed = null;
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
using (var gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
using (var memoryStream = new MemoryStream())
using (var compressionStream = new ZstandardStream(memoryStream, CompressionMode.Compress))
{
compressionStream.CompressionLevel = 11; // optional!!
//compressionStream.CompressionDictionary = dictionary; // optional!!
compressionStream.Write(gzipStream, 0, gzipStream.Length);
compressionStream.Close();
compressed = memoryStream.ToArray();
}
}
public static void ConvertToZstd(string path, string outputPath)
{
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
using (var gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
using (var memoryStream = new MemoryStream())
using (var compressionStream = new ZstandardStream(memoryStream, CompressionMode.Compress))
{
compressionStream.CompressionLevel = 11; // optional!!
//compressionStream.CompressionDictionary = dictionary; // optional!!
gzipStream.CopyTo(compressionStream);
compressionStream.Close();
File.WriteAllBytes(outputPath, memoryStream.ToArray());
}
}
This code will compress and serialize the object:
public static byte[] ObjectToByteArray(object[] obj)
{
using (MemoryStream msCompressed = new MemoryStream())
using (GZipStream gZipStream = new GZipStream(msCompressed, CompressionMode.Compress))
using (MemoryStream msDecompressed = new MemoryStream())
{
new BinaryFormatter().Serialize(msDecompressed, obj);
byte[] byteArray = msDecompressed.ToArray();
gZipStream.Write(byteArray, 0, byteArray.Length);
gZipStream.Close();
return msCompressed.ToArray();
}
}
And the following will upload it to the Azure Blob Storage:
byte[] byteObject = ObjectToByteArray(uploadObject);
using (Stream stream = new MemoryStream(byteObject))
{
stream.Seek(0, SeekOrigin.Begin);
blockBlob.UploadFromStream(stream, null, options);
}
This works great, but I can't find a way to download, decompress and deserialize this object/file from my storage.
You could use method DownloadToStream to download the file to local.
using (var fileStream = System.IO.File.OpenWrite(#"xxxx\compressedfile.gz"))
{
blockBlob.DownloadToStream(fileStream);
}
And then you could refer to the following code to decompress and deserialize the specified stream.
public static void DecompressAndDeserialize(string path)
{
using (FileStream originalFileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
FileInfo fileToDecompress = new FileInfo(path);
string FileName = fileToDecompress.FullName;
string newFileName = FileName.Remove(FileName.Length - fileToDecompress.Extension.Length);
using (FileStream decompressedFileStream = File.Create(newFileName))
{
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
{
decompressionStream.CopyTo(decompressedFileStream);
}
}
FileStream fs = new FileStream(newFileName, FileMode.Open);
BinaryFormatter formatter = new BinaryFormatter();
object[] uploadObject = (object[])formatter.Deserialize(fs);
}
}
I'm using the following code to generate an openxml document and save it on the server and that works fine, however now i'm trying to generate it to a byte stream to serve out straight away without saving to the server but the document gets corrupted in the process.
Working Code
public static void CreateWordDoc(List<objReplace> lstReplace, String TemplateFile, String OutputPath)
{
File.Delete(OutputPath);
File.Copy(TemplateFile, OutputPath);
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(OutputPath, true))
{
string docText = null;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
docText = sr.ReadToEnd();
foreach (var ro in lstReplace)
{
Regex regexText = new Regex(ro.Find);
docText = regexText.Replace(docText, ro.Replace);
}
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
}
}
Code that produces currupted XML - that I want to get working
public static byte[] CreateWordDocToStream(List<objReplace> lstReplace, String TemplateFile)
{
string docText = null;
byte[] filebytes = File.ReadAllBytes(TemplateFile);
using (MemoryStream stream = new MemoryStream(filebytes))
{
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(stream, true))
{
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
docText = sr.ReadToEnd();
foreach (var ro in lstReplace)
{
Regex regexText = new Regex(ro.Find);
docText = regexText.Replace(docText, ro.Replace);
}
}
}
return Encoding.ASCII.GetBytes(docText);
}
can someone tell me why I'm loosing information doing this process ? Some utf8 chars appears not decoded :
"Biography":"\u003clink type=... or Steve Blunt \u0026 Marty Kelley
but others do : "Name":"朱敬
// Creating a 64bit string containing gzip data
string bar;
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress))
using (StreamWriter writer = new StreamWriter(gzip, System.Text.Encoding.UTF8))
{
writer.Write(s);
}
ms.Flush();
bar = Convert.ToBase64String(ms.ToArray());
}
// Reading it
string foo;
byte[] itemData = Convert.FromBase64String(bar);
using (MemoryStream src = new MemoryStream(itemData))
using (GZipStream gzs = new GZipStream(src, CompressionMode.Decompress))
using (MemoryStream dest = new MemoryStream(itemData.Length*2))
{
gzs.CopyTo(dest);
foo = Encoding.UTF8.GetString(dest.ToArray());
}
Console.WriteLine(foo);
It could be because you are writing the string using StreamWriter but reading it using CopyTo() and Encoding.GetString().
What happens if you try this?
// Reading it
string foo;
byte[] itemData = Convert.FromBase64String(bar);
using (MemoryStream src = new MemoryStream(itemData))
using (GZipStream gzs = new GZipStream(src, CompressionMode.Decompress))
using (StreamReader reader = new StreamReader(gzs, Encoding.UTF8))
{
foo = reader.ReadLine();
}
Although I think you should be using BinaryReader and BinaryWriter:
string s = "Biography:\u003clink type...";
string bar;
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress))
using (var writer = new BinaryWriter(gzip, Encoding.UTF8))
{
writer.Write(s);
}
ms.Flush();
bar = Convert.ToBase64String(ms.ToArray());
}
// Reading it
string foo;
byte[] itemData = Convert.FromBase64String(bar);
using (MemoryStream src = new MemoryStream(itemData))
using (GZipStream gzs = new GZipStream(src, CompressionMode.Decompress))
using (var reader = new BinaryReader(gzs, Encoding.UTF8))
{
foo = reader.ReadString();
}
Console.WriteLine(foo);
The issue was simply that the characters were already encoded in the source string.
Ps : Credit goes to rik for this answer :)
Edit : I also had the StreamReader issue matthew-watson was suggesting.
The code below tries to fill the message byte array with some simple text until the buffer is filled.
byte[] message = new byte[1024];
using (MemoryStream memoryStream = new MemoryStream(message, true))
{
using (StreamWriter streamWriter = new StreamWriter(memoryStream, Encoding.ASCII))
{
while (???)
streamWriter.WriteLine("Hello World!");
}
}
What should be in the while(???) statement?
byte[] message = new byte[1024];
using (MemoryStream memoryStream = new MemoryStream(message, true))
{
using (StreamWriter streamWriter = new StreamWriter(memoryStream, Encoding.ASCII))
{
var lineToAdd = "Hello World!";
while (memoryStream.Length - memoryStream.Position > lineToAdd.Length)
{
streamWriter.WriteLine(lineToAdd);
streamWriter.Flush();
}
}
}
OR
using (MemoryStream memoryStream = new MemoryStream(message, true))
using (StreamWriter streamWriter = new StreamWriter(memoryStream, Encoding.ASCII))
{
streamWriter.AutoFlush = true;
var lineToAdd = "Hello World!";
while (memoryStream.Length - memoryStream.Position > lineToAdd.Length)
streamWriter.WriteLine(lineToAdd);
}