How does C# know the length of string using Binary Writer? - serialization

Please look at the code below. This program simply saves a 33-character-length string "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" with an additional byte value of "33".
using System.Text;
namespace Test
{
internal class Program
{
static void Main(string[] args)
{
string filepath = args[0];
using (var stream = File.Open(filepath, FileMode.Create))
{
using (var writer = new BinaryWriter(stream, Encoding.UTF8, false))
{
writer.Write(new string('!', 33));
writer.Write((byte)33);
}
}
using (var stream = File.Open(filepath, FileMode.Open))
{
using (var reader = new BinaryReader(stream, Encoding.UTF8, false))
{
Console.WriteLine(reader.ReadString());
Console.WriteLine(reader.ReadByte());
}
}
Console.ReadKey();
}
}
}
And here is the binary representation of it:
Apparently, the first starting "ox21" is the length of the string - but how on earth does C# know?

Related

Files not downloaded showing binay data in ASP.NET core web API

Trying to download multiplefile as zip using System.io.compression from asp.net core web api. But i got binary error text. How can i fix this? below is my code
Error:
Error from backend. {"headers":{"normalizedNames":{},"lazyUpdate":null},"status":200,"statusText":"OK","url":"http://localhost:4000/api/filegeneration/createfile/2023-02-08/1","ok":false,"name":"HttpErrorResponse","
message":"Http failure during parsing for http://localhost:4000/api/filegeneration/createfile/2023-02-08/1",
"error":{"error":{},"text":"PK\u0003\u0004\u0014\u0000\u0000\u0000\b\u0000��HV�
u0010\u0001\u000b\u0000\u0000\u0000\u0003\u0000\u0000\u0000\u001e\u0000\u0000\u0000
Fareshare_Qty_08.02.2023_0.txtz�{?\u0000\u0000\u0000��\u0003\u0000PK\u0001\u0002\u0014
\u0000\u0014\u0000\u0000\u0000\b\u0000��HV�\u0010\u0001\u000b\u0000\u0000\u0000\u0003\u0000\u0000
\u0000\u001e\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000Fareshare_Qty_08.02.2023_0.txtPK\u0005
\u0006\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000L\u0000\u0000\u0000G\u0000\u0000\u0000\u0000\u0000"}}
Controller:
using (var outstream = new MemoryStream())
{
using (var archive = new ZipArchive(outstream,ZipArchiveMode.Create,true))
{
foreach (string filePath in files)
{
var filearcive = archive.CreateEntry(Path.GetFileName(filePath),CompressionLevel.Optimal);
using (var entrystream = filearcive.Open())
{
using (var fileCompressionStream = new MemoryStream(System.IO.File.ReadAllBytes(filePath)))
{
await fileCompressionStream.CopyToAsync(entrystream);
}
}
}
}
outstream.Position = 0;
return File(outstream.ToArray(), "application/zip", "Fareshare.zip");
Below code works for me. Please check it.
public (string fileType, byte[] archiveData, string archiveName) DownloadFiles(string subDirectory)
{
var zipName = $"archive-{DateTime.Now.ToString("yyyy_MM_dd-HH_mm_ss")}.zip";
List<FileInfo> files = new DirectoryInfo(Path.Combine(_hostingEnvironment.ContentRootPath, subDirectory)).GetFiles().ToList();
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
files.ForEach(file =>
{
var theFile = archive.CreateEntry(file.Name);
using (var streamWriter = new StreamWriter(theFile.Open()))
{
streamWriter.Write(File.ReadAllText(file.FullName));
}
});
}
return ("application/zip", memoryStream.ToArray(), zipName);
}
Test Result

Save XDocument issue

I'm loading my document like so:
WebClient client = new WebClient();
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
client.OpenReadAsync(new Uri("Rolls.xml", UriKind.Relative));
Then on the Read Completed:
XDocument doc = XDocument.Load(XmlReader.Create(e.Result));
using (Stream stream = e.Result)
{
{
foreach (var roll in _rollsToAddStudentTo)
{
doc.Element("rolls").Add(new XElement("rollid", roll));
}
doc.Save(stream);
}
}
The problem is when it gets to the save I get the error
"Specified method is not supported."
Help will be much appreciated.
Cheers
Thanks Jehof,
So, how would I incorporate my document into that async method?
foreach (var roll in _rollsToAddStudentTo)
{
doc.Element("rolls").Add(new XElement("rollid", roll));
}
WebClient client = new WebClient();
client.OpenWriteCompleted += new OpenWriteCompletedEventHandler(client_OpenWriteCompleted);
client.OpenWriteAsync(new Uri("Rolls.xml", UriKind.Relative));
I have resolved this by changing my logic to below.
using (IsolatedStorageFile isoStore =
IsolatedStorageFile.GetUserStoreForApplication())
{
// Create new file
using (IsolatedStorageFileStream isoStream =
new IsolatedStorageFileStream("Rolls.xml",
FileMode.Create, isoStore))
{
// Write to the Isolated Storage for the user.
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
// Create an XmlWriter.
using (XmlWriter writer = XmlWriter.Create(isoStream, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement("Rolls");
foreach (var roll in _rollsToAddStudentTo)
{
writer.WriteStartElement("roll");
writer.WriteAttributeString("rollid", roll);
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.WriteEndDocument();
}
}
}
The stream you try to save the XDocument is readonly. Cause it is the stream you get passed as argument to your method client_OpenReadCompleted that is registered to the event OpenReadCompleted.
If you want to save your XDocument back via WebClient you need to call one of the OpenWriteAsync-methods.

SerializeObject and DeserializeObject

I use this following code but it gives error
Service1.svc.cs
public static byte[] SerializeObject<T>(T obj)
{
using (MemoryStream ms = new MemoryStream())
{
using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(ms))
{
DataContractSerializer dcs = new DataContractSerializer(typeof(T));
dcs.WriteObject(writer, obj); writer.Flush();
return ms.ToArray();
}
}
}
client code Windows phone
public static T DeserializeObject<T>(byte[] xml)
{
using (MemoryStream memoryStream = new MemoryStream(xml))
{
using (XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(memoryStream, XmlDictionaryReaderQuotas.Max))
{
DataContractSerializer dcs = new DataContractSerializer(typeof(T));
return (T)dcs.ReadObject(reader);
}
}
}
I call this DeserializeObject from below code
void svc_Get_Conn(object send, GetConnCompletedEventArgs e)
{
CookieContainer con =DeserializeObject<CookieContainer>(e.Result);
}
This gives following error
Message = "Type 'System.Net.PathList' with data contract name 'PathList:http://schemas.datacontract.org/2004/07/System.Net' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using...
How to solve this?
CookieContainer can't be serializable. Check this workaround
cheers

How to merge PDFs into a PDF Portfolio?

I am looking for the functionality that creates PDF Portfolios:
The image shows the free adobe reader that can be downloaded from Adobe (duh!). When I open this particular PDF, I was surprised that it has all these Layout, Files and Attachment features. It is definitely not the normal "PDF merge". It is more like a package with multiple PDFs.
Can itextsharp do this? What is the search term for this PDF functionality?
The term you're looking for is PDF Portfolios. You can create PDFs like this with iTextSharp. Here are a couple of C# examples from the iText book:
Chapter16 - KubrickCollection
Chapter16 - KubrickMovies
If you choose to download the KubrickMovies result file, change the extension to ".pdf". Just noticed it now - will try and fix the error this weekend.
To generate pdf portfolio (using iTextSharp) first we need to create a collection, then store it.
Example read one pdf file, create from it a collection of 2 files hello.pdf,united_states.pdf finally store as Test.pdf
static void Main(string[] args)
{
Document pdfDoc = null;
FileStream fstr = null;
try
{
pdfDoc = new Document(PageSize.A4);
fstr = new FileStream("Test.pdf", FileMode.Create);
var pdfWriter = PdfWriter.GetInstance(pdfDoc, fstr);
pdfDoc.Open();
pdfDoc.Add(new Chunk());
PdfCollection collection = new PdfCollection(PdfCollection.TILE);
var filePath = #"somePDF.pdf";
var fileInfo = new FileInfo(filePath);
var pdfDictionary = new PdfDictionary();
pdfDictionary.Put(PdfName.Moddate, new PdfDate(fileInfo.LastWriteTime));
pdfWriter.Collection = collection;
PdfFileSpecification fileSpec = PdfFileSpecification.FileEmbedded(
pdfWriter,
filePath,
fileInfo.Name,
null
);
pdfWriter.AddFileAttachment("united_states.pdf", fileSpec);
fileSpec = PdfFileSpecification.FileEmbedded(pdfWriter, filePath, fileInfo.Name, null);
pdfWriter.AddFileAttachment("hello.pdf", fileSpec);
pdfDoc.Close();
}
finally
{
pdfDoc.Close();
pdfDoc = null;
fstr.Close();
}
}
Here is the simple sample to show how we can attach files to a new PDF file:
using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace PDFAttachment
{
class Program
{
static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
var pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
pdfDoc.Open();
pdfDoc.Add(new Phrase("Test"));
var filePath = #"C:\path\logo.png";
var fileInfo = new FileInfo(filePath);
var pdfDictionary = new PdfDictionary();
pdfDictionary.Put(PdfName.MODDATE, new PdfDate(fileInfo.LastWriteTime));
var fs = PdfFileSpecification.FileEmbedded(pdfWriter, filePath, fileInfo.Name, null, true, null, pdfDictionary);
pdfWriter.AddFileAttachment("desc.", fs);
}
Process.Start("Test.pdf");
}
}
}
Or to an existing PDF file:
using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace PDFAttachment
{
class Program
{
static void Main(string[] args)
{
var reader = new PdfReader("Test.pdf");
using (var stamper = new PdfStamper(reader, new FileStream("newTest.pdf", FileMode.Create)))
{
var filePath = #"C:\path\logo.png";
addAttachment(stamper, filePath, "desc.");
stamper.Close();
}
Process.Start("newTest.pdf");
}
private static void addAttachment(PdfStamper stamper, string filePath, string description)
{
var fileInfo = new FileInfo(filePath);
var pdfDictionary = new PdfDictionary();
pdfDictionary.Put(PdfName.MODDATE, new PdfDate(fileInfo.LastWriteTime));
var pdfWriter = stamper.Writer;
var fs = PdfFileSpecification.FileEmbedded(pdfWriter, filePath, fileInfo.Name, null, true, null, pdfDictionary);
stamper.AddFileAttachment(description, fs);
}
}
}

How to Serialize CookieContainer in wp7 applications?

I tried to Serialize cookie to save it and Deserialize at next time I start my application.But the result of Deserialize is empty.What's wrong?
void SaveCookie() {
var appStorage = IsolatedStorageFile.GetUserStoreForApplication();
if (this.checkBox_save_passowrd.IsChecked == true)
{
CookieContainer cc = SEC_Services.Httprequest.cookie;
string fileName = "usercookie.xml";
using (var file = appStorage.OpenFile(fileName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write))
{
using (var writer = new StreamWriter(file))
{
System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(CookieContainer));
xs.Serialize(writer, cc);
writer.Close();
}
}
}
else {
if (appStorage.FileExists("usercookie.xml"))
{
appStorage.DeleteFile("usercookie.xml");
}
}
}
void ReadCookie() {
var appStorage = IsolatedStorageFile.GetUserStoreForApplication();
if (appStorage.FileExists("usercookie.xml"))
{
using (System.IO.StreamReader reader = new StreamReader(appStorage.OpenFile("usercookie.xml", FileMode.Open)))
{
System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(CookieContainer));
CookieContainer obj = (CookieContainer)xs.Deserialize(reader);
reader.Close();
SEC_Services.Httprequest.cookie = obj;
if (obj.Count != 0) {
NavigationService.Navigate(new Uri("/PanoramaPage.xaml", UriKind.Relative));
}
}
}
}
I also found this simple
C#: Writing a CookieContainer to Disk and Loading Back In For Use
shows that CookieContainer could be Serialize.But there is no SoapFormatter in wp7 library
IsolatedStorageSettings.ApplicationSettings["index"] = yourcookie;
So you don't need to serialize it.
I'm using it in a project
As the question is "How to Serialize CookieContainer" and the accepted answer doesn't really answer this. This is how to do it with serialization:
Write to disk:
public static void WriteCookiesToDisk(string file, CookieContainer cookieJar)
{
using(Stream stream = File.Create(file))
{
try {
Console.Out.Write("Writing cookies to disk... ");
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, cookieJar);
Console.Out.WriteLine("Done.");
} catch(Exception e) {
Console.Out.WriteLine("Problem writing cookies to disk: " + e.GetType());
}
}
}
Read from disk:
public static CookieContainer ReadCookiesFromDisk(string file)
{
try {
using(Stream stream = File.Open(file, FileMode.Open))
{
Console.Out.Write("Reading cookies from disk... ");
BinaryFormatter formatter = new BinaryFormatter();
Console.Out.WriteLine("Done.");
return (CookieContainer)formatter.Deserialize(stream);
}
} catch(Exception e) {
Console.Out.WriteLine("Problem reading cookies from disk: " + e.GetType());
return new CookieContainer();
}
}