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