Reputation: 2465
I'm quite new to C# (I'm using .NET 4.0) so please bear with me. I need to save some object properties (their properties are int, double, String, boolean, datetime) to a file. But I want to encrypt the files using my own encryption, so I can't use FileStream to convert to binary. Also I don't want to use object serialization, because of performance issues. The idea is simple, first I need to somehow convert objects (their properties) to binary (array), then encrypt (some sort of xor) the array and append it to the end of the file. When reading first decrypt the array and then somehow convert the binary array back to object properties (from which I'll generate objects).
I know (roughly =) ) how to convert these things by hand and I could code it, but it would be useless (too slow). I think the best way would be just to get properties' representation in memory and save that. But I don't know how to do it using C# (maybe using pointers?). Also I though about using MemoryStream but again I think it would be inefficient. I am thinking about class Converter, but it does not support toByte(datetime) (documentation says it always throws exception).
For converting back I think the only options is class Converter.
Note: I know the structure of objects and they will not change, also the maximum String length is also known.
Thank you for all your ideas and time.
EDIT: I will be storing only parts of objects, in some cases also parts of different objects (a couple of properties from one object type and a couple from another), thus I think that serialization is not an option for me.
Upvotes: 0
Views: 1295
Reputation: 134065
There are many different ways to do this. Perhaps the easiest, and performance should be adequate, would be to write each record to a MemoryStream
, get the resulting array of bytes, do your encryption on that array, and then write the array to file using FileStream
and a BinaryWriter
.
FileStream fs = new FileStream(...);
BinaryWriter fileWriter = new BinaryWriter(fs);
// Allocate byte array big enough to hold the longest record
byte[] RecordBuffer = new byte[MaxRecordSize];
int recordLength; // to get the number of bytes in a record.
// for each record
using (var ms = new MemoryStream())
{
using (var memWriter = new BinaryWriter(ms, Encoding.UTF8))
{
// write things to the memory stream
memWriter.Write(myStringValue);
memWriter.Write(myLongValue);
// ... etc.
// Now get the number of bytes written
memWriter.Flush();
recordLength = memWriter.Position;
}
}
// The record is now serialized in RecordBuffer, from 0 to recordLength-1
// Do your encryption.
// Then write a count of bytes, and the buffer:
fileWriter.Write(recordLength);
fileWriter.Write(RecordBuffer, 0, recordLength);
Reading that back in is quite easy. You set up a BinaryReader
on the file, call ReadInt32
to get the record length, call Read(RecordBuffer, 0, length)
to get the record bytes, do your decryption, and then use a MemoryStream
to de-serialize.
Upvotes: 1
Reputation: 207
I'm posting this as an answer since I'm too green to write comments.
Start out with serializing the entire classes like Jens and Xanatos said. Most likely this will be fine. The best way to find out is to try it.
If you really need to make the files smaller, then create new classes containing only the members that need to be serialized. When you go to write the file, you can convert your larger objects to the smaller format and serialize that, then when you load the file you can initialize the full objects from the smaller ones again.
Upvotes: 0
Reputation: 111920
You can serialize them with BinaryFormatter and, before writing them to the FileStream, encrypt them. This will write and read an object (I'm using a DateTime as an example)
using (FileStream sw = File.Create("D:\\Test.bin"))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(sw, DateTime.Now);
}
using (FileStream sw = File.Open("D:\\Test.bin", FileMode.Open))
{
BinaryFormatter bf = new BinaryFormatter();
DateTime dt2 = (DateTime)bf.Deserialize(sw);
}
If you simply want the "binary" content of a base type you can use:
Byte[] bytes = BitConverter.GetBytes(property)
For DateTime you save the Tick property (and if you want the Kind property). For string you use Encoding.UTF8.GetBytes.
Upvotes: 4