save and load a 2d array to a file

Ali Çehreli acehreli at yahoo.com
Tue Apr 19 06:05:27 UTC 2022


On 4/18/22 22:05, Chris Katko wrote:
 > ````D
 > struct map_t{
 > int data[50][50];
 > } map;

Hey! That's C! :)

 > //save
 > std.file.write("save.map", map.data); // compiles

That serializes the array byte-by-byte.

 > //load
 > map.data = std.file.read("save.map", map.data.sizeof); // error

And that does the same in reverse and returns void[], which means "just 
bytes".

 > main.d(536): Error: cannot implicitly convert expression
 > `read("save.map", 2500LU)` of type `void[]` to `ubyte[50][]`

One needs to cast that void[] to the proper type and than assign back. 
However... Instead of that, I like rawWrite and rawRead because both are 
typed and the latter reads on top of existing storage like map.data that 
you have here. So, no extra copy needed.

One quirk of rawWrite and rawRead is that they want slices of objects. 
It is a little awkward when there is just one thing to write and read. 
Uncompiled but something like this:

   int i = 42;
   file.rawWrite(*cast((int[1]*)(&i)));  // Casted to be an array of 1

 > I'm guessing here, that internally we've got an array of arrays (which
 > means array of pointers),

Not in the case of static arrays: What you have here is nothing 
different from 50x50 ints consecutively in memory.

import std.stdio;
import std.exception;
import std.conv;

struct map_t {
int[50][50] data;
}

void main() {
   map_t map;

   // Some interesting data
   foreach (r, ref row; map.data[]) {
     foreach (c, ref element; row[]) {
       element = (1000 * r + c).to!int;
     }
   }

   File("save.map", "w").rawWrite(map.data[]);

   map_t other;

   //load
   auto read = File("save.map").rawRead(other.data[]);
   enforce(read.length == map.data.length, "Failed to read all rows of 
the array.");
   enforce(map == other, "The arrays don't match.");
}

Ali



More information about the Digitalmars-d-learn mailing list