How do I iteratively replace lines in a file?

Kai Meyer kai at unixlords.com
Sun Mar 20 08:17:20 PDT 2011


On 03/19/2011 05:51 PM, Andrej Mitrovic wrote:
> I'm trying to do something like the following:
>
> File inputfile;
> foreach (string name; dirEntries(r".\subdir\", SpanMode.shallow))
> {
>      if (!(isFile(name)&&  getExt(name) == "d"))
>      {
>          continue;
>      }
>
>      inputfile = File(name, "a+");
>
>      foreach (line; inputfile.byLine)
>      {
>          if (line == "import foo.d")
>          {
>              inputfile.write("import bar.d");  // or ideally `line = "import bar.d"`
>          }
>      }
> }
>
> That obviously won't work. I think I might need to use the `fseek` function to keep track of where I am in the file, or something like that. File I/O in D is no fun..


The only problem with your approach that a "line" is an abstract 
concept. In a filesystem, there are only blocks of bytes. When you write 
(flush) a byte to a file, the file transaction is actually an entire 
block at a time (ext3 defaults to a 4k block, for example.) Lines are 
just an array of bytes. When dealing with (relatively) fast memory, 
modifying a line is pretty transparent. If you open a 1GB file and add 
bytes at the very beginning, the filesystem is quite likely to write out 
the entire file again.

I would suggest you write out to a temporary file, and then move the 
file on top of the original file.

foreach(name ...)
{
   inputfile = File(name, "r");
   outputfile = File("/tmp/" ~ name, "a");
   foreach(line ...)
   {
     do something to line
     outputfile.write(line);
   }
   outputfile.close();
   rename("/tmp" ~ name, name);
}

This will allow you to manipulate line by line, but it won't be 
in-place. This is the type of approach that a lot of text editors take, 
and a very common work around. If you were to encounter a language that 
allows you to read and write lines iteratively and in-place like this in 
a file, I'll bet you they are writing your changes to a temp file, and 
moving the file over the top of the original at the end (perhaps when 
you close()).



More information about the Digitalmars-d-learn mailing list