Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Writing a string to a file and reading it back

Moderators: larsivi kris

Posted: 10/11/08 00:19:01

Maybe something's wrong with me, but I'm consistently having an inordinate amount of trouble with simple file I/O tasks in Tango. This time, I simply want to write a string (of dynamic length) to a file and read it back in again.

Writing is simple enough:

auto stream = new DataOutput(new FileOutput(fname));
stream.put(mystring);

An inspection of the created binary output shows an integer indicating the length of the string followed by the string bytes themselves; as expected.

Now, when I try to read the string back again, I get into trouble:

auto stream = new DataInput(new FileInput(fname));
char[] mystring;
stream.get(mystring);

This doesn't work because get() expects the array it is passed already to be allocated to a sufficient size. Clearly, I can't do this because I don't know before the call to get() how long the string will be!

I can think of some kludgy workarounds, but is there a clean and simple standard way to do this? Especially taking into account that I want to interleave this call with calls to other DataStream? methods like getInt etc? Maybe a templated method DataInput?.getArray(T)() which would return a newly allocated array of the given type would be helpful?

Author Message

Posted: 10/11/08 00:24:36

To be clear, this is the workaround that I currently use and that seems to work fine:

T[] readArray(T)(DataInput s)
{
	int numEntries = s.getInt;
	T[] result = new T[numEntries];
	s.read(result);
	return result;
}

I'm just wondering if something like that is in Tango already, and if not, if it should be.

Posted: 10/11/08 01:46:22

Hi,

DataStream also supports reading and writing of raw data arrays, via a read(void[]) and write(void[]) methods. Unfortunately these don't show up in the documentation because they're inherited, and the doc generation does not support inheritance features at this time :(

However, the write() method does not inject a prefix, and the read() method does not expect one. This gives you the control to, for example, read an array length and allocate an appropriate destination array before using read(array) in order to populate it.

You may well ask why get() doesn't just do the allocation on your behalf instead? Well, maybe it should, though there's also a common need to avoid allocation altogether. Perhaps we should add a convenience reader method to perform an allocation as required?

Hope that helps?

Posted: 10/11/08 01:48:15 -- Modified: 10/11/08 02:07:28 by
kris

oh, duh ... just saw your second message ... just ignore me :)

I added a get() variation ... see if that suffices?

Posted: 10/15/08 02:41:53

Wait a moment... does put() write the size in bytes, not as the number of entries? Then my code above is wrong, isn't it? (I have only used it for chars so far.) The documentation for put() is slightly ambiguous in that respect.

Posted: 10/15/08 03:39:58

bytes :)