Importar archivo de texto como cadena de un solo carácter

204

¿Cómo se importa un archivo de texto sin formato como cadena de un solo carácter en R? Creo que esto probablemente tendrá una respuesta muy simple, pero cuando probé esto hoy descubrí que no podía encontrar una función para hacerlo.

Por ejemplo, supongamos que tengo un archivo foo.txtcon algo que quiero minar.

Lo probé con:

scan("foo.txt", what="character", sep=NULL)

pero esto todavía devolvió un vector. Lo tengo trabajando un poco con:

paste(scan("foo.txt", what="character", sep=" "),collapse=" ")

pero esa es una solución bastante fea que probablemente también sea inestable.

Sacha Epskamp
fuente
20
readr::read_fileresuelve este problema muy bien ahora.
Zach

Respuestas:

213

Aquí hay una variante de la solución de @JoshuaUlrich que usa el tamaño correcto en lugar de un tamaño codificado:

fileName <- 'foo.txt'
readChar(fileName, file.info(fileName)$size)

Tenga en cuenta que readChar asigna espacio para la cantidad de bytes que especifique, por lo readChar(fileName, .Machine$integer.max)que no funciona bien ...

Tommy
fuente
18
Vale la pena señalar que este código no funcionará para archivos comprimidos. En ese caso, el número de bytes devueltos por file.info (nombre de archivo) $ size no coincidirá con el contenido real que se leerá en la memoria, que esperamos sea mayor.
asieira
146

En caso de que alguien todavía esté analizando esta pregunta 3 años después, el paquete de lectura de Hadley Wickham tiene una read_file()función útil que lo hará por usted.

install.packages("readr") # you only need to do this one time on your system
library(readr)
mystring <- read_file("path/to/myfile.txt")
Sharon
fuente
2
Por desgracia, "read_file" no aparece en stringr ahora. :( cran.r-project.org/web/packages/stringr/stringr.pdf
Michael Lloyd Lee mlk
8
@mlk ha sido migrado a readr. He actualizado la respuesta en consecuencia, espero que a Sharon no le importe.
Nick Kennedy
2
bonito ! también descomprime archivos .gz sobre la marcha
Andre Holzner
Tengo could not find function "pase"en este código
Sashko Lykhenko
47

Yo usaría lo siguiente. Debería funcionar bien, y no me parece feo, al menos para mí:

singleString <- paste(readLines("foo.txt"), collapse=" ")
Josh O'Brien
fuente
15
Hubiera esperado collapse="\n"replicar el hecho de que estas son líneas separadas en el archivo original. Con este cambio, esta solución va a trabajar para los archivos comprimidos y sin comprimir igualmente bien.
asieira
Esto no parece funcionar. Si escribo líneas (singleString), obtengo un archivo dañado ...
bumpkin
Esto no funciona si la última línea no incluye un carácter de final de línea. En ese caso, la última línea no se incluye en la cadena (alternativamente, el archivo se trunca en el último salto de línea).
gvrocha
Esto funcionará bien para leer archivos de texto como en el queston del OP: las conexiones de archivos de texto son blocking=TRUEpor defecto, por lo readLines()que devolverá el archivo completo solo con una advertencia sobre el carácter EOL faltante. Sin embargo, vale la pena escuchar el comentario de @gvrocha: ¡comprenda su tipo de conexión! ? ayuda de readLines diceIf the final line is incomplete (no final EOL marker) the behaviour depends on whether the connection is blocking or not. For a non-blocking text-mode connection the incomplete line is pushed back, silently. **For all other connections the line will be accepted, with a warning.**
krads
15

Qué tal si:

string <- readChar("foo.txt",nchars=1e6)
Joshua Ulrich
fuente
8

El paquete de lectura tiene una función para hacer todo por usted.

install.packages("readr") # you only need to do this one time on your system
library(readr)
mystring <- read_file("path/to/myfile.txt")

Esto reemplaza la versión en el paquete stringr.

Mike Stanley
fuente
5

Lástima que la solución de Sharon ya no se pueda usar. He agregado la solución de Josh O'Brien con la modificación de asieira a mi archivo .Rprofile:

read.text = function(pathname)
{
    return (paste(readLines(pathname), collapse="\n"))
}

y utilizar de esta manera: txt = read.text('path/to/my/file.txt'). No pude replicar el hallazgo de bumpkin (28 oct. 14), y writeLines(txt)mostré el contenido de file.txt. Además, después de que write(txt, '/tmp/out')el comando diff /tmp/out path/to/my/file.txtno informó diferencias.

Frank B. Brokken
fuente
2

readChar no tiene mucha flexibilidad, por lo que combiné sus soluciones (readLines y paste).

También he agregado un espacio entre cada línea:

con <- file("/Users/YourtextFile.txt", "r", blocking = FALSE)
singleString <- readLines(con) # empty
singleString <- paste(singleString, sep = " ", collapse = " ")
close(con)
harris11
fuente
1

Parece que tu solución no es muy fea. Puede usar funciones y hacerlo profesional de esta manera

  • primera forma
new.function <- function(filename){
  readChar(filename, file.info(filename)$size)
}

new.function('foo.txt')
  • segunda forma
new.function <- function(){
  filename <- 'foo.txt'
  return (readChar(filename, file.info(filename)$size))
}

new.function()
Kalana
fuente
1
Esto no agrega nada a la respuesta proporcionada por @Tommy . Proporcionar ruta dentro de un entorno funcional es una solución particularmente pobre.
Konrad el