rguides

writeLines()

writeLines(text, con = stdout(), sep = "\n", useBytes = FALSE)

writeLines() writes each element of a character vector as a separate line to a file or connection. It handles line endings automatically, converting the separator to the platform-native format by default. This makes it a straightforward choice for exporting text data from R.

Syntax

writeLines(text, con = stdout(), sep = "\n", useBytes = FALSE)

Parameters

ParameterTypeDefaultDescription
textcharacter,A character vector whose elements will become separate lines
conconnection or characterstdout()File path (character string) or an active connection
sepcharacter"\\n"String appended after each line
useByteslogicalFALSEIf TRUE, pass strings byte-by-byte without re-encoding

Return value

Returns NULL invisibly. The function is called primarily for its side effect of writing to a connection or file.

Examples

Writing to a file

# Basic file output
lines <- c("First line", "Second line", "Third line")
writeLines(lines, "output.txt")

# Read back to confirm
readLines("output.txt")
# [1] "First line"  "Second line" "Third line"

Controlling the line separator

Unix systems use \n (LF) as the line terminator, while Windows uses \r\n (CRLF). By default, writeLines() converts the separator to the platform-native format automatically. This means the same R script produces correct line endings whether it runs on a Linux server or a Windows desktop, without any conditional logic. If you need a specific line-ending style regardless of the host platform, pass the sep argument explicitly.

# Explicit LF separator (Unix-style even on Windows)
writeLines(c("line a", "line b"), "unix.txt", sep = "\n")

# CRLF for Windows compatibility
writeLines(c("line a", "line b"), "windows.txt", sep = "\r\n")

Using a file path vs. a connection

When you pass a character string as con, writeLines() opens a file connection for the duration of the call, then closes it automatically. This is the simplest pattern for one-off writes. If you pass an already-open connection, writeLines() writes from the current position and leaves the connection open, allowing multiple writes to the same file handle before a single close() call. This approach avoids the overhead of repeatedly opening and closing the file.

# Opening a connection manually gives more control
con <- file("log.txt", open = "wt")
writeLines("Application started", con)
writeLines("Data loaded successfully", con)
close(con)

# Passing a file path is simpler for one-off writes
writeLines(c("entry one", "entry two"), "simple.txt")

Working with encodings

By default, R converts strings with marked encodings to the current locale before writing them to the connection. Set useBytes = TRUE to suppress this re-encoding step entirely. This is useful when you have already handled encoding conversion with iconv() and want to write the raw byte sequences without R applying a second transformation. Be cautious with useBytes = TRUE on Windows, where the system encoding may not match your output bytes, leading to garbled text in the resulting file.

# Force byte-level output without re-encoding
writeLines("\u00e9cole", "french.txt", useBytes = TRUE)

Appending to existing files

writeLines() overwrites the target file by default. To add lines to an existing file without erasing its current contents, open a connection in append mode with file("log.txt", open = "a"). Each subsequent writeLines() call to that connection appends to the end. This pattern is common in logging workflows where you accumulate output across multiple steps of a script without holding the entire log in memory.

writeLines("First batch", "log.txt")
# Open in append mode
con <- file("log.txt", open = "a")
writeLines("Second batch", con)
close(con)

readLines("log.txt")
# [1] "First batch"  "Second batch"

Common patterns

Exporting a character vector, one element per line: This is the most direct use of writeLines() — each string in the input vector becomes a separate line in the output file. The function writes exactly the character data, with no added quotes, row numbers, or other R formatting artifacts. For tabular data with multiple fields per row, combine fields with paste() before passing the result to writeLines().

words <- c("apple", "banana", "cherry")
writeLines(words, "fruit.txt")
# File contains:
# apple
# banana
# cherry

Writing lines from a loop with progress logging: When processing a sequence of files or iterations, appending status lines to a log file gives you a durable record of what happened. Set append = TRUE so each writeLines() call adds a new entry rather than clobbering the previous one. For long-running jobs, writing a log entry after each iteration lets you monitor progress with tail -f on the log file from a separate terminal.

for (i in seq_along(files)) {
  writeLines(paste("Processing", files[i]), "progress.log", append = TRUE)
}

writeLines() vs cat() vs print()

writeLines() is the cleanest option when you have a character vector and want each element on its own line. It writes exactly what you give it, no quotation marks, no extra formatting, no [1] index prefixes.

cat() gives more control over the separator between elements. Use it when you want to join strings with custom delimiters or mix literals and variables in one call. Unlike writeLines(), cat() does not add a trailing newline by default.

print() and message() add formatting around the output (quotes around strings, [1] prefixes, stderr for messages). They are intended for interactive display rather than writing to files.

For large character vectors, writeLines() opens a connection once and writes in a single batch, making it more efficient than calling cat() in a loop.

See also

  • readLines(), read lines from a file or connection
  • cat(), concatenate and print with more formatting control
  • print() — print R objects with quotation marks