www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.file vs std.stream

reply Ludovic A. <ludovica axis.com> writes:
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:

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?

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?
Mar 04 2010
parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
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
Mar 04 2010
next sibling parent reply Ludovic A. <ludovica axis.com> writes:
Hej,

thanks! First I want to underline that I use Digital Mars D Compiler v2.040, and
my 2 examples are _working_ examples with this compiler. So I really mean that
std.file is working on the last D compiler :)

I felt that those examples didn't 'smell' like D, and I also got some import
conflicts when I tried to import both std.stream and std.file in the same time.
It's clearer now ;)

I am still suprised that I don't have to indicate the type of "line", but I
guess
it is deduced from whatever file.byLine returns. I will dig out the foreach
implementation, sounds pretty cool anyway.

Last but not least, I extensively used the Search function of the Digitalmars
website, and I did see information about std.stream / std.file popping on the
top
results. The Search function also referenced quite a lot of posts in
"/archives/"
:) I looked at tutorials on dsource, it seems most of them are outdated... Hence
my questions: where can I found the last up-to-date D standard well presented
like
a Javadoc?
Mar 04 2010
parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Ludovic A. wrote:
 Hej,
 
 thanks! First I want to underline that I use Digital Mars D Compiler v2.040,
and
 my 2 examples are _working_ examples with this compiler. So I really mean that
 std.file is working on the last D compiler :)
 
 I felt that those examples didn't 'smell' like D, and I also got some import
 conflicts when I tried to import both std.stream and std.file in the same time.
 It's clearer now ;)
 
 I am still suprised that I don't have to indicate the type of "line", but I
guess
 it is deduced from whatever file.byLine returns. I will dig out the foreach
 implementation, sounds pretty cool anyway.
 
 Last but not least, I extensively used the Search function of the Digitalmars
 website, and I did see information about std.stream / std.file popping on the
top
 results. The Search function also referenced quite a lot of posts in
"/archives/"
 :) I looked at tutorials on dsource, it seems most of them are outdated...
Hence
 my questions: where can I found the last up-to-date D standard well presented
like
 a Javadoc?

Short answer: You can't. :) Long answer: Like I said, Phobos is a work in progress, and now that the language specification itself has been frozen, you can expect big changes to the library in the near future. The best guide to which parts of Phobos are newest (and therefore less likely to change in the future) is the changelog. The major changes started with DMD 2.029: http://www.digitalmars.com/d/2.0/changelog.html#new2_029 -Lars
Mar 04 2010
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
Lars T. Kyllingstad wrote:

 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.

I've been using std.stream.File because it uses the generic Stream interface like dout and din does. Using std.stream.File should allow cleaner template code without needing 'static if' and other conditional compilation features.
 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);
   }

std.stdio.File has two advantages that I've discovered so far: - As you also note, it closes the file immediately. With std.stream.File, I have to use 'scope' objects - It allows chosing text vs. binary file I/O mode. std.stream.Stream.writefln always converts the newline character according to the system Ali
Mar 04 2010
parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Ali Çehreli wrote:
 Lars T. Kyllingstad wrote:
 
  > 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.
 
 I've been using std.stream.File because it uses the generic Stream 
 interface like dout and din does.
 
 Using std.stream.File should allow cleaner template code without needing 
 'static if' and other conditional compilation features.

Unfortunately it has the major drawback of not working anymore when std.stream is deprecated. -Lars
Mar 04 2010