Thread overview
reading a structure (eg header info) from file
Jul 03, 2013
captaindet
Jul 04, 2013
Rikki Cattermole
Jul 04, 2013
Ali Çehreli
Jul 04, 2013
Jonathan M Davis
Jul 04, 2013
captaindet
Jul 04, 2013
bearophile
July 03, 2013
hi,

whilst converting some of my C code into D i got stuck.

in C:

typedef struct { /* info */ } INFO;
INFO info;
size_t checkio;
// read INFO from data file:
pf_datafile = fopen("datafile","rb");
checkio = fread((char *) &info, sizeof(info), 1, pf_datafile);

how do i do this in D? i'd like to avoid falling back to calling C functions, but i cannot figure out how do this with phobos functions. mind you, eventually the INFO struct might be anywhere in the file, not only at the beginning.

cheers,

det  

July 04, 2013
On Wednesday, 3 July 2013 at 20:37:24 UTC, captaindet wrote:
> hi,
>
> whilst converting some of my C code into D i got stuck.
>
> in C:
>
> typedef struct { /* info */ } INFO;
> INFO info;
> size_t checkio;
> // read INFO from data file:
> pf_datafile = fopen("datafile","rb");
> checkio = fread((char *) &info, sizeof(info), 1, pf_datafile);
>
> how do i do this in D? i'd like to avoid falling back to calling C functions, but i cannot figure out how do this with phobos functions. mind you, eventually the INFO struct might be anywhere in the file, not only at the beginning.
>
> cheers,
>
> det

Take a look at http://dlang.org/phobos/std_file.html#.read
There is also http://dlang.org/phobos/std_file.html#.readText if you wish to read a whole file as text.

When I tested it things like string didn't work but numbers did.
Maybe someone else here can help you if you need that.
July 04, 2013
On 07/03/2013 01:37 PM, captaindet wrote:

> in C:
>
> typedef struct { /* info */ } INFO;
> INFO info;
> size_t checkio;
> // read INFO from data file:
> pf_datafile = fopen("datafile","rb");
> checkio = fread((char *) &info, sizeof(info), 1, pf_datafile);

Just a reminder: The operation above is not portable. There are endianness and struct member padding issues.

> how do i do this in D?

Assuming that the writer and the reader agree that it works, the closest in Phobos is std.stdio.rawRead.

> the INFO struct might be anywhere in the file, not only at the beginning.

seek() does that.

import std.stdio;

struct Info
{
    size_t a;
    double b;
    byte c;
}

void main()
{
    auto info0 = Info(1, 2.25, 3);
    auto info1 = Info(4, 5.50, 6);

    writeTest("test_file", [ info0, info1 ]);
    readTest("test_file", 0);
    readTest("test_file", 1);
}

void writeTest(string fileName, const(Info)[] infos)
{
    auto file = File(fileName, "w");

    file.rawWrite(infos);
}

void readTest(string fileName, size_t index)
{
    auto file = File(fileName, "r");

    auto offset = index * Info.sizeof;
    file.seek(offset);

    // More than 1 would read as many elements
    auto info = new Info[1];
    file.rawRead(info);

    writefln("Read Info at index %s: %s", index, info);
}

Ali

July 04, 2013
On Wednesday, July 03, 2013 15:37:28 captaindet wrote:
> hi,
> 
> whilst converting some of my C code into D i got stuck.
> 
> in C:
> 
> typedef struct { /* info */ } INFO;
> INFO info;
> size_t checkio;
> // read INFO from data file:
> pf_datafile = fopen("datafile","rb");
> checkio = fread((char *) &info, sizeof(info), 1, pf_datafile);
> 
> how do i do this in D? i'd like to avoid falling back to calling C functions, but i cannot figure out how do this with phobos functions. mind you, eventually the INFO struct might be anywhere in the file, not only at the beginning.

You should probably look at std.stdio.File. It looks like its readf function might be what you're looking for. If not, there are quite a few functions on there, and it's likely that you could get one of them to do what you want.

Or you could always use std.mmfile.MmFile and operate on the file as an array and do it all that way (memory-mapped I/O is one of the coolest things ever IMHO).

- Jonathan M Davis
July 04, 2013
thanks everyone for your help!

i should have mentioned that i did play with std.stdio.File.readf
and rawRead but was too thick to figure out a working solution.

o i could not figure out how to make readf work with my self
defined struct

o same with rawRead. but here i understand my mistake now: i have
to pass an array of my struct, even if i only want to read it
once.

endianness and padding are certainly issues. i have spent some
time figuring out how to adjust struct packing in D. my
definitions are now full of align(2) declarations... as for the
endianness, as i can oversee it now all potential users will sit
on little-endian machines. the group of users is small, just our
workgroup.

the datafiles in question are produced by some 3rd party 16bit
windows software, so i have to accept the way the data is stored
in the file. also, they can be as big as 2GB so reading in the
whole file is not an option.

thanks again,

det
July 04, 2013
captaindet:

> as for the
> endianness, as i can oversee it now all potential users will sit
> on little-endian machines. the group of users is small, just our
> workgroup.

If you are able to put a tag in your file that specifies the endianess, using Phobos it's not hard to convert the data to the right endianess of the CPU where the D code is running.

Bye,
bearophile