5

Following my questions about storing data, it has been suggested that I could use XML but then obfuscate the file by encoding it using Base64. I like this idea, and I have achieved what I want in XML, but I don't know how to save it in Base64. This is my code so far:

XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;

XmlWriter write = XmlWriter.Create("C:\\Users\\Andy\\Desktop\\database.xml", settings);
write.WriteStartDocument();
write.WriteStartElement("Database");
write.WriteStartElement("Entry");
write.WriteAttributeString("key", "value");
write.WriteEndElement();
write.WriteEndElement();

write.Flush();
write.Close();
Dan Homola
  • 3,819
  • 1
  • 28
  • 43
Andy
  • 3,600
  • 12
  • 53
  • 84

4 Answers4

5

Write it:

var sb = new StringBuilder(); 
var settings = new XmlWriterSettings();
//..settings
using (var writer = XmlWriter.Create(sb, settings))
{
    //...
}
//http://stackoverflow.com/questions/1564718/using-stringwriter-for-xml-serialization
var encoding = new UnicodeEncoding(); 
string s = Convert.ToBase64String(encoding.GetBytes(sb.ToString()));

File.WriteAllText("c:\temp.txt", s);

Read it:

string readText = File.ReadAllText("c:\temp.txt");
byte[] toDecodeByte = Convert.FromBase64String(readText);

using (var stream = new MemoryStream(toDecodeByte))
{
    using (XmlReader reader = XmlReader.Create(stream))
    {
        //.. read your xml
    }
}
giammin
  • 18,620
  • 8
  • 71
  • 89
  • Thank you for your answer. I would like to encode the entire XML file though, so could you please expand on that part. – Andy Jul 24 '13 at 14:04
  • +1 Thank you for the edit. So would I then just use a writer object to write `s` to a file? Also, I know I didn't ask it originally but could you show me how to read the XML file as well please? – Andy Jul 24 '13 at 14:12
  • @Andy the fastest way is to use System.IO.File.WriteAllText – giammin Jul 24 '13 at 14:25
  • Thank you. I'm new to C# and I'm still learning. Could you show me how to reverse that process and get the `XmlReader` object please? – Andy Jul 24 '13 at 14:34
  • This wont compile: `The best overloaded method match for 'System.Convert.ToBase64String(byte[])' has some invalid arguments` – SwDevMan81 Jul 24 '13 at 14:55
  • 2
    Please do not use `ASCIIEncoding`. You should use `UTF8Encoding`. – Jim Mischel Jul 24 '13 at 15:43
  • @giammin Thanks very much. Just what I was after, but yeah, I'm not going to use `ASCIIEncoding` :) May I just ask if there is a reason you don't use a `MemoryStream` when writing the file? – Andy Jul 24 '13 at 15:51
  • @Andy you have to use ASCIIEncoding because base64 is ASCII. File.WriteAllText is shorter to write and internally it uses a streamwriter :D – giammin Jul 24 '13 at 15:54
  • @giammin Ah ok, that's fair enough. Could the same method be used for UTF8? Do I actually need UTF8? – Andy Jul 24 '13 at 16:18
  • @Andy sorry I made a mistake: base64 is Ascii but we are reading a string before converting to base64! in xml is better UTF16 – giammin Jul 24 '13 at 16:29
  • @Andy about utf16, xml and c# string http://stackoverflow.com/questions/1564718/using-stringwriter-for-xml-serialization – giammin Jul 24 '13 at 16:39
  • @giammin So, if you are converting UTF16 to ASCII/Base64, does that mean that only characters in the ASCII character set can be supported? – Andy Jul 24 '13 at 17:32
  • You're right: base64 is ASCII and there's no need to use UTF8 encoding. No reason not too, either. But I was wrong to criticize your use of ASCII here. My apologies. – Jim Mischel Jul 24 '13 at 19:23
  • @JimMischel Will the method above mean that Unicode (non-ASCII) characters can't be included in the XML file though? – Andy Jul 24 '13 at 19:46
  • 1
    @Andy: You CAN include non-ASCII characters in the XML, regardless of whether you use ASCII or UTF8 when writing the base64 string. As was pointed out, base64 encodes binary data using only ASCII characters--that's the whole point of it. When it's decoded, you get back the original binary data. – Jim Mischel Jul 24 '13 at 20:15
  • @Andy sorry, I was out. Jim is right. Base64 encoding will handle non ascii chars. – giammin Jul 25 '13 at 09:33
  • @JimMischel The only downside to use Utf8 encoding for a base64 string is that you waste a bit for every char.. we can live with that :D – giammin Jul 25 '13 at 09:35
  • It's ok. No problem. So will encoding the file significantly increase the size of the XML file? Does the amount it affects the file size increase with the original size of the file? – Andy Jul 25 '13 at 10:48
  • @Andy not significantly. don't understand the second question – giammin Jul 25 '13 at 11:03
  • @giammin I mean, if the file is larger when it isn't encoded, will encoding impact the size more than it would do a smaller XML file? i.e is the amount encoding affects a file size proportionate to the non-encode file size? – Andy Jul 25 '13 at 11:11
  • @giammin: UTF8 and ASCII would give the same size output for a base64 encoded string. – Jim Mischel Jul 25 '13 at 12:43
  • @Andy: base64 requires 4 characters to encode every 3 bytes. The encoded file will be larger than the original file. The encoded size will be `(4 * original_size)/3`. – Jim Mischel Jul 25 '13 at 12:45
  • @JimMischel Thank you very much, that's exactly what I was looking for. One more question: how much extra time does it take to encode data? It may seem a strange comparison, but would it be any faster than compression? – Andy Jul 25 '13 at 12:59
  • @JimMischel yes, I meant that if you encode a file in utf8 instead of ascii for a base64 content you 'll have a little bigger file – giammin Jul 25 '13 at 13:01
  • @Andy imho compression is always slower but never tested it – giammin Jul 25 '13 at 13:03
  • 2
    @Andy: Compression and/or any non-trivial encryption (anything beyond a simple substitution cipher) will be slower than base64 encoding. base64 encoding is a very simple transformation. It will take longer to write the encoded string to disk than it takes to encode the string. – Jim Mischel Jul 25 '13 at 14:22
3

You need to convert your xmlwriter to string like this

 using (var sw = new StringWriter()) {
 using (var xw = XmlWriter.Create(sw)) {
// Build Xml with xw.


   }
  return sw.ToString();
}

then convert your string to Base64. and write it to file

Ehsan
  • 31,833
  • 6
  • 56
  • 65
1

This will have the information that you are looking for:

http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.writebase64.aspx

HTH,

d3

aydjay
  • 858
  • 11
  • 25
1

Here is an example using a MemoryStream

Save the XML data using MemoryStream to base64 encode the data and write it to a file.

using (var ms = new MemoryStream())
{   
    // Memory Stream
    using (XmlWriter writer = XmlWriter.Create(ms,settings)) 
    {
        writer.WriteStartDocument();
        writer.WriteStartElement("Database");
        writer.WriteStartElement("Entry");
        writer.WriteAttributeString("key", "value");
        writer.WriteEndElement();
        writer.WriteEndElement();

        writer.Flush();
        writer.Close();

        // XML Data (Debug)
        Console.WriteLine(new UTF8Encoding().GetString(ms.ToArray()));

        // Pre encoding hex (Debug)
        Console.WriteLine(BitConverter.ToString(ms.ToArray()));

        string s = Convert.ToBase64String(ms.ToArray());
        Console.WriteLine(s); // (Debug)

        // Post encoding
        File.WriteAllText(@"C:\Temp\A.enc", s);
    }
}

Read the file back

// Read encoded file back to xml
string enc_text = File.ReadAllText(@"C:\Temp\A.enc");
Console.WriteLine(enc_text); // (Debug)

// Pre encoding hex
byte[] mem_bytes = Convert.FromBase64String(enc_text);
Console.WriteLine(BitConverter.ToString(mem_bytes)); // (Debug)

// XML Data
Console.WriteLine(new UTF8Encoding().GetString(mem_bytes));

// Read byte array into Reader
using (var stream = new MemoryStream(mem_bytes))
{
    using (XmlReader reader = XmlReader.Create(stream))
    {
        // Use reader as desired
    }
}
SwDevMan81
  • 48,814
  • 22
  • 151
  • 184
  • Thank you very much for your answer. Regarding reading the file back, how could I actually get the data in the XmlReader rather than just print it? Which `Stream` object would be best to use? – Andy Jul 24 '13 at 15:28
  • @Andy - I updated to show how to create the XmlReader from the byte array data. – SwDevMan81 Jul 24 '13 at 15:46
  • Thank you very much. I thought it would be something like that, but I'm very new to C#. – Andy Jul 24 '13 at 15:52