在R中,“connection”是什么意思?

56
我已经阅读并成功使用了 R 中的 ?connections,但我真的不理解它们是什么。
我知道我可以下载文件,读写压缩文件...(也就是说,我理解使用连接(打开,操作,关闭)的结果,但我真的不知道它们实际上是做什么的,为什么你必须打开和关闭它们等等)。
我希望这也能帮助我更有效地使用它们(主要是理解正在发生的机制,以便在出现问题时能有效地进行调试)。
1个回答

95

连接是在R 1.2.0中引入的,由Brian Ripley在R NEWS的第一期(现在称为The R Journal)(2001年1月第16-17页)中描述为抽象接口,用于处理诸如文件、url、套接字或管道等IO流。2013年,Simon Urbanek添加了Connections.h C API,使R软件包能够实现自定义连接类型,例如curl软件包。

连接的一个特点是可以使用readBinwriteBinreadLineswriteLines函数从连接中逐步读取或写入数据。这允许进行异步数据处理,例如处理大量数据或网络连接时:

# Read the first 30 lines, 10 lines at a time
con <- url("http://jeroen.github.io/data/diamonds.json") 
open(con, "r")
data1 <- readLines(con, n = 10)
data2 <- readLines(con, n = 10)
data3 <- readLines(con, n = 10)
close(con)

对于写入文件,同样适用:

tmp <- file(tempfile())
open(tmp, "w")
writeLines("A line", tmp)
writeLines("Another line", tmp)
close(tmp)

rbwb方式打开连接读取/写入二进制数据(在R中称为原始向量):

# Read the first 3000 bytes, 1000 bytes at a time
con <- url("http://jeroen.github.io/data/diamonds.json") 
open(con, "rb")
data1 <- readBin(con, raw(), n = 1000)
data2 <- readBin(con, raw(), n = 1000)
data3 <- readBin(con, raw(), n = 1000)
close(con)

pipe()连接用于运行系统命令,并像在Shell中使用|运算符一样将文本管道到stdin或从stdout管道输出。例如(让我们继续使用curl示例),您可以运行curl命令行程序并将其输出导入到R中:

con <- pipe("curl -H 'Accept: application/json' https://jeroen.github.io/data/diamonds.json")
open(con, "r")
data1 <- readLines(con, n = 10)
data2 <- readLines(con, n = 10)
data3 <- readLines(con, n = 10)

连接的某些方面可能会让人感到困惑:要逐步读取/写入数据,您需要显式地打开(open())和关闭(close())连接。但是,readLineswriteLines会自动打开和关闭(但不会销毁!)未打开的连接。因此,下面的示例将一遍又一遍地读取前10行,这并没有什么用:

con <- url("http://jeroen.github.io/data/diamonds.json") 
data1 <- readLines(con, n = 10)
data2 <- readLines(con, n = 10)
data3 <- readLines(con, n = 10)
identical(data1, data2)

另一个需要注意的事情是,C API 可以同时 关闭销毁 连接,但 R 只公开了一个名为 close() 的函数,它实际上意味着销毁。 在连接上调用 close() 后,它将被销毁并变得完全无用。

要从连接中流处理数据,可以使用类似以下模式的方法:

stream <- function(){
  con <- url("http://jeroen.github.io/data/diamonds.json")
  open(con, "r")
  on.exit(close(con))
  while(length(txt <- readLines(con, n = 10))){
    some_callback(txt)
  } 
}

jsonlite软件包在导入/导出ndjson数据时依赖于连接:

library(jsonlite)
library(curl)
diamonds <- stream_in(curl("https://jeroen.github.io/data/diamonds.json"))

流式传输(默认每次1000行)使其快速且内存使用效率高:

library(nycflights13)
stream_out(flights, file(tmp <- tempfile()))
flights2 <- stream_in(file(tmp))
all.equal(flights2, as.data.frame(flights))

最后,关于连接的一个好处是,如果您忘记关闭它们,垃圾回收器将自动关闭它们,并发出令人恼火的警告:

con <- file(system.file("DESCRIPTION"), open = "r")
rm(con)
gc()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接