std.file vs std.stream

Lars T. Kyllingstad public at kyllingen.NOSPAMnet
Thu Mar 4 06:51:21 PST 2010


Ludovic A. wrote:
> I am trying to write a simple file parser in D2. Following examples I found 2
> working ways to read a line and print it:


Where did you find the examples?  They seem pretty out-of-date.


> import std.stream
> (...)
>   Stream file = new BufferedFile(filename);
>   foreach(char[] line; file)
>   {
>     writefln("line: %s",line);
>   }
> 
> OR
> 
> import std.file;
> (...)
> File* file = new File(filename);
>    while (!file.eof())
>    {
>      writef("%s", file.readln());
>    }
> 
> My question from there is what is the difference between opening a stream and
> a file _in this case_, and what is the most appropriate in this case?


Did you really mean 'import std.file' up there, or did you mean 'import 
std.stdio' -- because that's where the File type is defined.

What you're seeing here is actually a consequence of Phobos very much 
being a work-in-progress.  std.stdio was completely rewritten about a 
year ago, and it most likely contains what you're looking for.

std.stream, on the other hand, hasn't seen major updates since 2005 or 
so, and is most likely an old left-over from D1.  I suspect it will be 
removed soon, or at least completely rewritten to adhere to the range 
interface.


So, my advice is to use std.stdio.File, and to use it like this:

   import std.stdio;
   ...
   auto file = File(filename);
   foreach (line; file.byLine)
   {
       writeln(line);
   }

Two things one should be aware of with the above example:

   1. File is a struct, not a class, which is why I didn't 'new' it.
      However, under the hood it works as a reference type, does its
      own reference counting, and will close the file *immediately*
      when there are no more references to it (i.e. the last copy of
      'file' goes out of scope).

   2. file.byLine returns a range that iterates over the lines of the
      file.  The 'line' variable is a char[] because the buffer is
      reused for each iteration, whereas the string type is immutable.
      Thus, if you want to store the contents of the 'line' array
      somewhere you need to copy it.

The std.stdio docs (with a few examples) can be found here:

   http://www.digitalmars.com/d/2.0/phobos/std_stdio.html


> Also in the foreach I can not write foreach (string line, file) but I have to
> use char[]. Is there a way to go around this?
> 
> Finally I can not use foreach in the std.file example, because the compiler
> says "foreach: File* is not an aggregate type". I was surprised that foreach
> worked on a Stream at the first place, so no big deal :) But what do we have
> under the hood? How can it work for Stream and not for File? Is the limitation
> coming from the foreach implementation?


I'm beginning to suspect you are using an ancient version of DMD2.  Am I 
right?

-Lars


More information about the Digitalmars-d-learn mailing list