R 中的连接到底是什么?
What exactly is a connection in R?
我已经通读并在 R 中成功使用了 ?connections
,但我真的不明白它们是什么。
我知道我可以下载文件、读取和写入压缩文件,...(我明白使用连接(打开、执行操作、关闭)的结果是什么,但是我真的不明白他们到底做了什么,为什么你必须打开和关闭它们等等)。
我希望这也能帮助我了解如何更有效地使用它们(主要是了解正在发生的事情的机制,这样我就可以在出现问题时有效地进行调试)。
连接是在 R 1.2.0 中引入的,Brian Ripley 在 January 2001 (page 16-17) as an abstracted interface to IO streams such as a file, url, socket, or pipe. In 2013, Simon Urbanek added a Connections.h C API which enables R packages to implement custom connection types, such as the curl 包的第一期 R 新闻(现在称为 R 期刊)中进行了描述。
连接的一个特性是您可以使用 readBin
、writeBin
、readLines
和 [=22] 增量读取或写入数据片段 from/to =] 功能。这允许异步数据处理,例如在处理大数据或网络连接时:
# 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)
打开 rb
或 wb
到 read/write 二进制数据(在 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()
连接用于 运行 系统命令和管道文本到 stdin
或从 stdout
就像你对 |
所做的那样shell 中的运算符。例如。 (让我们继续使用 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)
连接的某些方面有点令人困惑:要递增 read/write 数据,您需要显式 open()
和 close()
连接。但是,readLines
和 writeLines
会自动打开和关闭(但不会破坏!)未打开的连接。因此,下面的示例将一遍又一遍地读取前 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 可以 close 和 destroy 一个连接,但是 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
包严重依赖与 import/export 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()
我已经通读并在 R 中成功使用了 ?connections
,但我真的不明白它们是什么。
我知道我可以下载文件、读取和写入压缩文件,...(我明白使用连接(打开、执行操作、关闭)的结果是什么,但是我真的不明白他们到底做了什么,为什么你必须打开和关闭它们等等)。
我希望这也能帮助我了解如何更有效地使用它们(主要是了解正在发生的事情的机制,这样我就可以在出现问题时有效地进行调试)。
连接是在 R 1.2.0 中引入的,Brian Ripley 在 January 2001 (page 16-17) as an abstracted interface to IO streams such as a file, url, socket, or pipe. In 2013, Simon Urbanek added a Connections.h C API which enables R packages to implement custom connection types, such as the curl 包的第一期 R 新闻(现在称为 R 期刊)中进行了描述。
连接的一个特性是您可以使用 readBin
、writeBin
、readLines
和 [=22] 增量读取或写入数据片段 from/to =] 功能。这允许异步数据处理,例如在处理大数据或网络连接时:
# 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)
打开 rb
或 wb
到 read/write 二进制数据(在 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()
连接用于 运行 系统命令和管道文本到 stdin
或从 stdout
就像你对 |
所做的那样shell 中的运算符。例如。 (让我们继续使用 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)
连接的某些方面有点令人困惑:要递增 read/write 数据,您需要显式 open()
和 close()
连接。但是,readLines
和 writeLines
会自动打开和关闭(但不会破坏!)未打开的连接。因此,下面的示例将一遍又一遍地读取前 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 可以 close 和 destroy 一个连接,但是 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
包严重依赖与 import/export 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()