Thread overview
r/w binary
Jun 28, 2011
Joel Christensen
Jun 29, 2011
Ali Çehreli
Jun 29, 2011
Joel Christensen
Jun 29, 2011
Joel Christensen
Jun 29, 2011
Ali Çehreli
Jun 30, 2011
Joel Christensen
Jun 30, 2011
Ali Çehreli
Jun 30, 2011
Joel Christensen
Jun 30, 2011
Ali Çehreli
Jul 01, 2011
Joel Christensen
June 28, 2011
I want to save and load levels for my game. The std.stream module doesn't have much examples.

Here is my code:
void saveLevel( string fileName ) {
	auto bfile = new std.stream.File;

	int ver = 1;
	string verStr = "version:";
	with( bfile ) {
		scope( exit )
			close;
		create( fileName );
		write( verStr ); write( ver ); // version
	}

	int ver2;
	char[] verStr2;
	auto bfile2 = new std.stream.File;
	with( bfile2 ) {
		scope( exit )
			close;
		create( fileName );
		read( verStr2 ); read( ver2 ); // version
	}
	writeln( verStr, ver );
}

And this is the result:
std.stream.ReadException@std\stream.d(46): Stream is not readable

- Joel
June 29, 2011
I've settled on std.stdio as opposed to std.stream and std.cstream.

On Wed, 29 Jun 2011 10:07:13 +1200, Joel Christensen wrote:

> I want to save and load levels for my game. The std.stream module doesn't have much examples.
> 
> Here is my code:
> void saveLevel( string fileName ) {
> 	auto bfile = new std.stream.File;
> 
> 	int ver = 1;
> 	string verStr = "version:";
> 	with( bfile ) {
> 		scope( exit )
> 			close;
> 		create( fileName );
> 		write( verStr ); write( ver ); // version
> 	}
> 
> 	int ver2;
> 	char[] verStr2;
> 	auto bfile2 = new std.stream.File;
> 	with( bfile2 ) {
> 		scope( exit )
> 			close;
> 		create( fileName );

That is copy-paste mistake, right? You don't want create() before reading. You must have meant open:

		open( fileName );

It works with that change.

> 		read( verStr2 ); read( ver2 ); // version
> 	}
> 	writeln( verStr, ver );
> }
> 
> And this is the result:
> std.stream.ReadException@std\stream.d(46): Stream is not readable
> 
> - Joel

Ali
June 29, 2011
Thanks for your reply Ali.

Your right about changing create to open when reading. And, yes, I was thinking of trying std.stdio myself.

- Joel

On 29-Jun-11 6:48 PM, Ali Çehreli wrote:
> I've settled on std.stdio as opposed to std.stream and std.cstream.
>
> On Wed, 29 Jun 2011 10:07:13 +1200, Joel Christensen wrote:
>
>> I want to save and load levels for my game. The std.stream module
>> doesn't have much examples.
>>
>> Here is my code:
>> void saveLevel( string fileName ) {
>> 	auto bfile = new std.stream.File;
>>
>> 	int ver = 1;
>> 	string verStr = "version:";
>> 	with( bfile ) {
>> 		scope( exit )
>> 			close;
>> 		create( fileName );
>> 		write( verStr ); write( ver ); // version
>> 	}
>>
>> 	int ver2;
>> 	char[] verStr2;
>> 	auto bfile2 = new std.stream.File;
>> 	with( bfile2 ) {
>> 		scope( exit )
>> 			close;
>> 		create( fileName );
>
> That is copy-paste mistake, right? You don't want create() before
> reading. You must have meant open:
>
> 		open( fileName );
>
> It works with that change.
>
>> 		read( verStr2 ); read( ver2 ); // version
>> 	}
>> 	writeln( verStr, ver );
>> }
>>
>> And this is the result:
>> std.stream.ReadException@std\stream.d(46): Stream is not readable
>>
>> - Joel
>
> Ali

June 29, 2011
With the char[], I can't use spaces in it the way I've got it here, (like if I tried using a phrase):

void saveLevel( string fileName ) {
	int ver = 1;
	auto house = "two".dup;
	double rnum = 3.0;
	
	{
		auto fout = File( fileName, "wb"); // open for binary writing
		scope( exit )
			fout.close;
		fout.writef( "%d %s %f", ver, house, rnum );
	}
	
	ver = 593;
	house = "asdfghf".dup;
	rnum = 57.23;

	{
		auto fin = File( fileName, "rb"); // open for binary reading
		scope( exit )
			fin.close;
		fin.readf( "%d %s %f", &ver, &house, &rnum );
	}

	writeln( "\nint: ", ver, " string: '", house, "' rnum: ", rnum );
}

- Joel
June 29, 2011
On Wed, 29 Jun 2011 19:55:38 +1200, Joel Christensen wrote:

> With the char[], I can't use spaces in it the way I've got it here,
> (like if I tried using a phrase):

There has been a thread very recently about reading strings. Look for the thread "readf with strings" (dated 22-Jun-2011 in my reader). Or, if it works here:

http://www.digitalmars.com/webnews/newsgroups.php? art_group=digitalmars.D.learn&article_id=27762

Reading the entire line:

    string s = chomp(readln());

Kai Meyer suggested parsing the string directly:

     string[] buffer;
     int a;
     float b;
     string c;
     buffer = chomp(readln()).split(" ");
     a = to!(int)(buffer[0]);
     b = to!(float)(buffer[1]);
     c = buffer[2..$].join(" ");
     writef("Read in: '%d' '%f' '%s'\n", a, b, c);

> 
> void saveLevel( string fileName ) {
> 	int ver = 1;
> 	auto house = "two".dup;
> 	double rnum = 3.0;
> 
> 	{
> 		auto fout = File( fileName, "wb"); // open for binary
writing scope(
> 		exit )
> 			fout.close;

You are not supposed to need to close the File object yourself. Being a struct, its destructor should be called automatically.

Ali
June 30, 2011
I'm thinking more about handling binary files. With the C version I would write a int for how many letters in the string, then put in the the string along side ([0005][house]). That way I can have any character at all (though I just thinking of char's).

Actually, I've just looked the output file and it's a text file. So in that case I would use read line to have spaces in strings, though what if I wanted to have new line character(s) in the one string. I still want to work with binary files.

On 30-Jun-11 2:23 AM, Ali Çehreli wrote:
> On Wed, 29 Jun 2011 19:55:38 +1200, Joel Christensen wrote:
>
>> With the char[], I can't use spaces in it the way I've got it here,
>> (like if I tried using a phrase):
>
> There has been a thread very recently about reading strings. Look for the
> thread "readf with strings" (dated 22-Jun-2011 in my reader). Or, if it
> works here:
>
> http://www.digitalmars.com/webnews/newsgroups.php?
> art_group=digitalmars.D.learn&article_id=27762
>
> Reading the entire line:
>
>      string s = chomp(readln());
>
> Kai Meyer suggested parsing the string directly:
>
>       string[] buffer;
>       int a;
>       float b;
>       string c;
>       buffer = chomp(readln()).split(" ");
>       a = to!(int)(buffer[0]);
>       b = to!(float)(buffer[1]);
>       c = buffer[2..$].join(" ");
>       writef("Read in: '%d' '%f' '%s'\n", a, b, c);
>
>>
>> void saveLevel( string fileName ) {
>> 	int ver = 1;
>> 	auto house = "two".dup;
>> 	double rnum = 3.0;
>> 	
>> 	{
>> 		auto fout = File( fileName, "wb"); // open for binary
> writing scope(
>> 		exit )
>> 			fout.close;
>
> You are not supposed to need to close the File object yourself. Being a
> struct, its destructor should be called automatically.
>
> Ali

June 30, 2011
On Thu, 30 Jun 2011 15:52:59 +1200, Joel Christensen wrote:

> I'm thinking more about handling binary files. With the C version I would write a int for how many letters in the string, then put in the the string along side ([0005][house]). That way I can have any character at all (though I just thinking of char's).

I would still use a portable text format myself.

For binary, you should consider rawWrite() and rawRead(). Here is just a start:

import std.stdio;

void main()
{
    int i = 42;
    auto file = File("deleteme.bin", "w");
    file.rawWrite((&i)[0..1]);
}

(Aside: The 'b' for binary mode does nothing in POSIX systems; so it's not necessary.)

The parameter to rawWrite() above is a nice feature of D: slicing a raw pointer produces a safe slice:

  http://digitalmars.com/d/2.0/arrays.html

<quote>
Slicing is not only handy for referring to parts of other arrays, but for
converting pointers into bounds-checked arrays:

int* p;
int[] b = p[0..8];
</quote>

For strings (actually arrays), you would need .length and .ptr properties.

I've never used it but you might want to consider the serialization library Orange as well:

  http://www.dsource.org/projects/orange

Ali
June 30, 2011
Yes, portability, I hadn't thought of that.

Shouldn't file.rawWrite((&i)[0..1]); have [0..4]? Or am I missing some thing?

- Joel

On 30-Jun-11 7:53 PM, Ali Çehreli wrote:
> On Thu, 30 Jun 2011 15:52:59 +1200, Joel Christensen wrote:
>
>> I'm thinking more about handling binary files. With the C version I
>> would write a int for how many letters in the string, then put in the
>> the string along side ([0005][house]). That way I can have any character
>> at all (though I just thinking of char's).
>
> I would still use a portable text format myself.
>
> For binary, you should consider rawWrite() and rawRead(). Here is just a
> start:
>
> import std.stdio;
>
> void main()
> {
>      int i = 42;
>      auto file = File("deleteme.bin", "w");
>      file.rawWrite((&i)[0..1]);
> }
>
> (Aside: The 'b' for binary mode does nothing in POSIX systems; so it's
> not necessary.)
>
> The parameter to rawWrite() above is a nice feature of D: slicing a raw
> pointer produces a safe slice:
>
>    http://digitalmars.com/d/2.0/arrays.html
>
> <quote>
> Slicing is not only handy for referring to parts of other arrays, but for
> converting pointers into bounds-checked arrays:
>
> int* p;
> int[] b = p[0..8];
> </quote>
>
> For strings (actually arrays), you would need .length and .ptr properties.
>
> I've never used it but you might want to consider the serialization
> library Orange as well:
>
>    http://www.dsource.org/projects/orange
>
> Ali

June 30, 2011
On Fri, 01 Jul 2011 05:28:56 +1200, Joel Christensen wrote:

> Shouldn't file.rawWrite((&i)[0..1]); have [0..4]? Or am I missing some
> thing?

[0..1] follows the regular slicing syntax there: those are element indexes. Since &i is an int*, [0..1] slices the first int. It would be different if it were ubyte* or void*.

Ali
July 01, 2011
Ok, I get you. A whole int*, not one byte of the int* data.

- Joel

On 01-Jul-11 6:07 AM, Ali Çehreli wrote:
> On Fri, 01 Jul 2011 05:28:56 +1200, Joel Christensen wrote:
>
>> Shouldn't file.rawWrite((&i)[0..1]); have [0..4]? Or am I missing some
>> thing?
>
> [0..1] follows the regular slicing syntax there: those are element
> indexes. Since&i is an int*, [0..1] slices the first int. It would be
> different if it were ubyte* or void*.
>
> Ali