442

In the R scripting language, how do I write lines of text, e.g., the following two lines

Hello
World

to a file named "output.txt"?

AndrewGB
  • 16,126
  • 5
  • 18
  • 49
amarillion
  • 24,487
  • 15
  • 68
  • 80

13 Answers13

543
fileConn<-file("output.txt")
writeLines(c("Hello","World"), fileConn)
close(fileConn)
Mark
  • 106,305
  • 20
  • 172
  • 230
  • 8
    Mark - what If I have several threads all of which I would like to add lines to the same file? (The issue being is that you can't have more then one connection to a file, If I am not mistaken) Thanks. – Tal Galili Mar 18 '10 at 15:02
  • 12
    @Tal, that is an excellent question, you should post it as a new, separate question so it'll get some attention. There are much more knowledgeable R programmers around here than me! – Mark Mar 18 '10 at 15:21
  • 12
    Note that this requires the file "output.txt" to already exist. If it doesn't, it must be created first, e.g. using 'file.create("output.txt")'. – Eike P. Aug 29 '14 at 12:26
  • 24
    @jhin I am not sure if that is true. Using RStudio 0.98 and R version 3.1.0 the file is created automatically if it doesn't exist – JHowIX Sep 10 '14 at 14:09
  • 1
    @JHowIX I just tried reproducing my issue and I can't. Not sure what my problem was at the time, but now everything seems to work as you say. Thanks for the hint! – Eike P. Oct 06 '14 at 12:47
  • 6
    The option of `writeLines()` is roughly ten times faster then the combination of `sink()` and `cat()` – rafa.pereira Oct 01 '15 at 09:36
  • 1
    You need not open and close the file because writeLines() will do that for you. See @petermeissner's answer. – Oliver Bock Dec 01 '16 at 00:55
  • @Mark `> coefficients<-file("coefficients") > writeLines(summary(model),coefficients) Error in writeLines(summary(model), coefficients) : invalid 'text' argument` – alhelal Nov 14 '17 at 04:40
  • `close` will return an error because **`writeLines` already closes the connection**. From `?writeLines`: "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." –  Dec 06 '18 at 09:19
  • @user57423, actually no. The full docs say `If the con is a character string, the function calls file to obtain a file connection which is opened for the duration of the function call. 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.` Which means if the `con` argument is a string, R assumes it to be a file path and opens a connection. If R opens the connection, it closes it. In my code snippet, I'm passing in a connection and R will not auto-close it. – Mark Dec 06 '18 at 13:05
  • @Mark You are right. I missed the `file()`. The same code without `file()` – i.e. `fileConn<-"output.txt"` – writes the same file, but returns `Error in UseMethod("close") : no applicable method for 'close' applied to an object of class "character"`. –  Dec 06 '18 at 20:32
  • 1
    `writeLines(c("Hello","World"), "output.txt")` does the opening and closing automatically like in the given answer. – Gwang-Jin Kim Jun 20 '19 at 16:18
  • @TalGalili did you ask that excellent question of yours in comments (multithread read / write to the same file) anywhere in SO ? Can you please post a link to that, it would add to this thread's value. Thanks. – Lazarus Thurston Dec 14 '21 at 11:19
185

Actually you can do it with sink():

sink("outfile.txt")
cat("hello")
cat("\n")
cat("world")
sink()

hence do:

file.show("outfile.txt")
# hello
# world
Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
aL3xa
  • 35,415
  • 18
  • 79
  • 112
  • sink() doesn't work on Databricks be careful. You can use put all these inside a function and call this function like capture.output(funciton call, filename) – abdkumar Jan 05 '20 at 04:18
  • Thanks for this @aL3xa. But keep in mind that this code effectively writes everything from the console, including the code exectured. – don_Gunner94 Nov 25 '20 at 12:21
146

I would use the cat() command as in this example:

> cat("Hello",file="outfile.txt",sep="\n")
> cat("World",file="outfile.txt",append=TRUE)

You can then view the results from with R with

> file.show("outfile.txt")
hello
world
ps1
  • 1,461
  • 1
  • 9
  • 2
83

What's about a simple writeLines()?

txt <- "Hallo\nWorld"
writeLines(txt, "outfile.txt")

or

txt <- c("Hallo", "World")
writeLines(txt, "outfile.txt")
petermeissner
  • 12,234
  • 5
  • 63
  • 63
  • 5
    nice to show that the input doesn't have to be a vector of lines – tim Sep 09 '14 at 16:30
  • 2
    @tim Actually `"Hallo\nWorld"` is a length one vector of the character type. Just try `txt <- "Hallo\nWorld"; is.character(txt) && length(txt) == 1 && is.vector(txt)` – zero323 Nov 13 '14 at 10:48
  • This works for me only as `writeLines(txt, con="outfile.txt")`. – Palec Apr 13 '15 at 16:31
  • nope, should work without naming arguments as long as you give a valid file name as second argument. – petermeissner Apr 15 '15 at 12:25
  • @petermeissner `> coefficients<-summary(model) > writeLines(coefficients, "coefficients") Error in writeLines(coefficients, "coefficients") : invalid 'text' argument` – alhelal Nov 14 '17 at 04:39
  • You cannot simply write anything to a file (*"invalid 'text' argument"*). It has to be character vector: e.g.:``library(magrittr); data.frame(y=1:10, x=rnorm(10)) %>% lm() %>% summary() %>% capture.output() %>% writeLines("coef.txt"); readLines("coef.txt")`` – petermeissner Nov 14 '17 at 07:47
26

I suggest:

writeLines(c("Hello","World"), "output.txt")

It is shorter and more direct than the current accepted answer. It is not necessary to do:

fileConn<-file("output.txt")
# writeLines command using fileConn connection
close(fileConn)

Because the documentation for writeLines() says:

If the con is a character string, the function calls file to obtain a file connection which is opened for the duration of the function call.

# default settings for writeLines(): sep = "\n", useBytes = FALSE
# so: sep = "" would join all together e.g.
Gwang-Jin Kim
  • 9,303
  • 17
  • 30
24

You could do that in a single statement

cat("hello","world",file="output.txt",sep="\n",append=TRUE)
Charan Raj
  • 471
  • 5
  • 8
20

Short ways to write lines of text to a file in R could be realised with cat or writeLines as already shown in many answers. Some of the shortest possibilities might be:

cat("Hello\nWorld", file="output.txt")
writeLines("Hello\nWorld", "output.txt")

In case you don't like the "\n" you could also use the following style:

cat("Hello
World", file="output.txt")

writeLines("Hello
World", "output.txt")

While writeLines adds a newline at the end of the file what is not the case for cat. This behaviour could be adjusted by:

writeLines("Hello\nWorld", "output.txt", sep="") #No newline at end of file
cat("Hello\nWorld\n", file="output.txt") #Newline at end of file
cat("Hello\nWorld", file="output.txt", sep="\n") #Newline at end of file

But main difference is that cat uses R objects and writeLines a character vector as argument. So writing out e.g. the numbers 1:10 needs to be casted for writeLines while it can be used as it is in cat:

cat(1:10)
writeLines(as.character(1:10))

and cat can take many objects but writeLines only one vector:

cat("Hello", "World", sep="\n")
writeLines(c("Hello", "World"))

Append to an existing file is easier with cat.

cat("Hello\n", file="output.txt")
cat("World", file="output.txt", append=TRUE)

writeLines("Hello", "output.txt")
CON <- file("output.txt", "a")
writeLines("World", CON)
close(CON)

On the other hand writeLines is faster than cat.

bench::mark(check=FALSE,
writeLines(c("Hello", "World")),
cat("Hello", "World", sep="\n"),
writeLines(c("Hello", "World"), sep=" "),
cat(c("Hello", "World")),
cat("Hello", "World") )
#  expression                                      min   median `itr/sec` mem_a…¹
#  <bch:expr>                                 <bch:tm> <bch:tm>     <dbl> <bch:b>
#1 writeLines(c("Hello", "World"))              2.27µs   4.77µs   163878.      0B
#2 cat("Hello", "World", sep = "\n")            3.83µs   8.51µs   118708.      0B
#3 writeLines(c("Hello", "World"), sep = " ")   1.99µs   4.25µs   235944.      0B
#4 cat(c("Hello", "World"))                      4.1µs   6.84µs   141797.      0B
#5 cat("Hello", "World")                        3.46µs   7.06µs   129865.      0B
GKi
  • 37,245
  • 2
  • 26
  • 48
10

tidyverse edition with pipe and write_lines() from readr

library(tidyverse)
c('Hello', 'World') %>% write_lines( "output.txt")
Yuriy Barvinchenko
  • 1,465
  • 1
  • 12
  • 17
5

What about a simple write.table()?

text = c("Hello", "World")
write.table(text, file = "output.txt", col.names = F, row.names = F, quote = F)

The parameters col.names = FALSE and row.names = FALSE make sure to exclude the row and column names in the txt, and the parameter quote = FALSE excludes those quotation marks at the beginning and end of each line in the txt. To read the data back in, you can use text = readLines("output.txt").

ATH
  • 666
  • 6
  • 13
2

To round out the possibilities, you can use writeLines() with sink(), if you want:

> sink("tempsink", type="output")
> writeLines("Hello\nWorld")
> sink()
> file.show("tempsink", delete.file=TRUE)
Hello
World

To me, it always seems most intuitive to use print(), but if you do that the output won't be what you want:

...
> print("Hello\nWorld")
...
[1] "Hello\nWorld"
gung - Reinstate Monica
  • 11,583
  • 7
  • 60
  • 79
2

Based on the best answer:

file <- file("test.txt")
writeLines(yourObject, file)
close(file)

Note that the yourObject needs to be in a string format; use as.character() to convert if you need.

But this is too much typing for every save attempt. Let's create a snippet in RStudio.

In Global Options >> Code >> Snippet, type this:

snippet wfile
    file <- file(${1:filename})
    writeLines(${2:yourObject}, file)
    close(file)

Then, during coding, type wfile and press Tab.

Palec
  • 12,743
  • 8
  • 69
  • 138
Luis Martins
  • 1,572
  • 12
  • 11
  • The `file <- file(...)` line looks suspicious to me. Isn't it both invoking `file` as a function and assigning `file` a new meaning? Does `file()` work even after this piece of code runs? Don't have access to an R installation to test myself right now... – Palec Aug 01 '17 at 19:29
  • it worked on my setup @Palec You can change file to youFile if you have some problem with reserved words – Luis Martins Aug 02 '17 at 19:37
1

The ugly system option

ptf <- function (txtToPrint,outFile){system(paste(paste(paste("echo '",cat(txtToPrint),sep = "",collapse = NULL),"'>",sep = "",collapse = NULL),outFile))}
#Prints txtToPrint to outFile in cwd. #!/bin/bash echo txtToPrint > outFile
kpie
  • 9,588
  • 5
  • 28
  • 50
0

In newer versions of R, writeLines will preserve returns and spaces in your text, so you don't need to include \n at the end of lines and you can write one big chunk of text to a file. This will work with the example,

txt <- "Hello
World"
fileConn<-file("output.txt")
writeLines(txt, fileConn)
close(fileConn)

But you could also use this setup to simply include text with structure (linebreaks or indents)

txt <- "Hello
   world
 I can 
   indent text!"
fileConn<-file("output.txt")
writeLines(txt, fileConn)
close(fileConn)
mikey
  • 1,066
  • 9
  • 17