A bit of binary I/O
Jarrett Billingsley
kb3ctd2 at yahoo.com
Sat Jan 20 15:45:18 PST 2007
"Heinz" <billgates at microsoft.com> wrote in message
news:eou69k$8tf$1 at digitaldaemon.com...
> The first way is to write primitives manually one by one:
>
> // primitive way
> ulong i = 9;
> char[] s = "hello world";
> myFile.writeExact(&i, i.sizeof);
> myFile.writeExact(&s, s.sizeof);
>
> Reading data:
> // Is done by reading each primitive.
> ulong i2; char[] s2;
> myFile.readExact(&i2, i2.sizeof);
> myFile.readExact(&s2, s2.sizeof);
You're writing the string wrong. All you're doing is writing the length and
pointer of the array data, without actually writing the data.
The Stream class (and by extension, the File class) provides functions for
writing out every basic type:
ulong i = 9;
char[] s = "hello world";
myFile.write(i);
myFile.write(s);
...
ulong i2;
char[] s2;
myFile.read(i2);
myFile.read(s);
> The second way is to write a structure with all the primitives as members:
>
> // struct way
> struct t
> {
> ulong i;
> char[] s;
> }
>
> t mt;
> mt.i = 9;
> mt.s = "hello world";
> myFile.writeExact(&mt, mt.sizeof);
>
> Reading data:
> // We read the entire struct.
> t mt2;
> myFile.readExact(&mt2, mt2.sizeof);
Again, you're just writing out the array reference without writing its
contents. You have to write out each member individually. If there were no
reference types in the struct, this would work fine.
>
> And the third way is to write a class with all the primitives as members:
>
> // class way
> class tt
> {
> ulong i;
> char[] s;
> }
>
> tt mtt = new tt();
> mtt.i = 9;
> mtt.s = "hello world";
> ResFile.writeExact(&mtt, mtt.sizeof);
>
> Reading data:
> // We read the entire class.
> tt mtt2;
> myFile.readExact(&mtt2, mtt2.sizeof);
>
This is incorrect, and is only working because of how you've written your
program. You're not writing the data out at all, you're writing a class
reference. The 00913FC0 is just the memory address of the class instance
that mtt points to, and when you read that address back in, you're just
looking at the data in memory. This program wouldn't work if you write the
file, exited, then had another program that read the data. You'd end up
with a memory access violation, and none of the data in the class is
actually written out.
If you want to write a class out to a file, a common way is to have some
kind of generic "serialize" and "unserialize" functions for the class:
class C
{
ulong i;
char[] s;
void serialize(Stream s)
{
s.write(i);
s.write(s);
}
static C unserialize(Stream s)
{
C c = new C();
s.read(c.i);
s.read(c.s);
return c;
}
}
...
C c = new C();
c.i = 5;
c.s = "foo";
c.serialize(myFile);
...
C c = C.unserialize(myFile);
>
> All of these methods works perfect. I'm able to retrieve values from all
> of them. Now lets check at the outputs:
>
> // Primitive
>
> 09 00 00 00 00 00 00 00 0B 00 00 00 A0 C7 41 00
>
> // Structure
>
> 09 00 00 00 00 00 00 00 0B 00 00 00 A0 C7 41 00
>
> // Class
>
> C0 3F 91 00
>
> My questions are:
>
> 1) What's the best method to write data (in terms of data
> protection/encryption against reversion). The class way seems to me at
> first look the most secure way.
As explained before, the class method is wrong, and there is no encryption
going on here. It's just a memory address, and you should never, ever write
memory addresses to a file.
That being said, the best way is probably to just use the primitive .read
and .write methods of File. Just .. never, ever write pointers or
references of any kind to a file.
> 2) Wich method is the faster in retrieving data?
If you implement them correctly, all three sample programs should make the
exact same output file using the same number of writes (and read it in the
same number of reads), and so they are all the same in terms of performance.
More information about the Digitalmars-d-learn
mailing list