Search code examples
rfilefile-iofile-writing

R file function: what the default value of open actually does?


Take this example, where we use the default value of the open parameter of the file function:

❯ R
> fh <- file("test.txt")
> writeLines("1", fh)
> writeLines("2", fh)
> close(fh)
> quit()

The resulting file only contains the last line:

❯ cat test.txt 
2

which seems a wrong behavior, I would expected both lines to be present.

Now take this example when we set open="w":

❯ R
> fh <- file("test.txt","w")
> writeLines("1",fh)
> writeLines("2",fh)
> close(fh)
> quit()

Now both lines are correctly written:

❯ cat test.txt
1
2

The documentation of file says:

The mode of a connection is determined when actually opened, which is deferred if ‘open = ""’ is given.

So it looks like the mode is set by writeLines. Its docs say:

If the connection is open it is written from its current position. If it is not open, it is opened for the duration of the call in ‘"wt"’ mode and then closed again.

And the docs for file says that wt is equivalent to w:

‘"w"’ or ‘"wt"’ Open for writing in text mode.

So since the two ways open the file in the same mode, I don't understand why they give different results.


Solution

  • The file is defined as read with your initial file open. If you read further in the documentation it states that

    Most operations that need write access or text-only or binary-only mode will override the default mode of a non-yet-open connection.

    So each time you call writeLines() you are temporarily overwriting the initial read mode. The file isn't opened in the CWD until you call writeLines().

    After you call

    > writeLines("1", fh)
    

    There is a file that contains 1 named test.txt

    After you call

    > writeLines("2", fh)
    

    The other writeLines() is overwritten and the file now contains 2.

    One can run this and watch the CWD and check the text file after each writeLines()

    You could run this and notice that fh stays in read mode the entire time

    fh <- file("c:/data/test.txt")
    writeLines("1", fh)
    # check contents of test.txt
    writeLines("2", fh)
    # check contents of test.txt
    stringy <- readLines(fh)
    print(stringy)