简而言之
这是一种便携式的方法,使用cURL并且不需要挂载远程文件系统:
> install.packages("curl")
> require("curl")
> handle <- new_handle()
> handle_setopt(handle, username = "domain\\username")
> handle_setopt(handle, password = "secret") # If needed
> request <- curl_fetch_memory("smb://host.example.com/share/file.txt", handle = handle)
> contents <- rawToChar(request$content)
如果我们需要像问题中那样读取CSV内容,可以通过另一个函数对文件进行流式传输:
> stream <- curl("smb://host.example.com/share/file.txt", handle = handle)
> contents <- read.csv(stream)
让我们来看一种更健壮的通过 URL访问远程文件的方法,除了其他答案中描述的挂载远程文件系统的方法。不幸的是,我有点晚了,但我希望这对未来的读者有所帮助。
在某些情况下,我们可能没有挂载文件系统所需的特权(这需要许多系统上的管理员或root访问权限),或者我们仅仅是不想挂载整个文件系统来读取单个文件。我们将使用
cURL库来读取文件。这种方法提高了程序的灵活性和可移植性,因为我们不需要依赖于外部挂载的文件系统的存在。我们将研究两种不同的方式:通过一个
system()
调用,以及使用提供cURL API的包。
一些背景知识:对于那些不熟悉它的人来说,cURL提供了用于在各种协议上传输数据的工具。自
7.40版本以来,cURL支持SMB/CIFS协议,通常用于Windows文件共享服务。cURL包括
一个命令行工具,我们可以使用它来获取文件的内容:
$ curl -u 'domain\username' 'smb://host.example.com/share/file.txt'
上述命令将以指定用户身份在域上认证,从远程服务器host.example.com读取并输出(到STDOUT)file.txt的内容。如果需要,该命令会提示我们输入密码。如果我们的网络不使用域名,可以从用户名中删除域部分。
系统调用
我们可以通过使用
system()函数在R中实现相同的功能:
system("curl -u 'domain\\username' 'smb://host.example.com/share/file.txt'")
注意
domain\\username
中的双反斜杠。这是为了转义反斜杠字符,使R不会将其解释为字符串中的转义字符。我们可以通过将
system()
函数的
intern
参数设置为
TRUE
,将命令输出的文件内容捕获到变量中:
contents <- system("curl -u 'domain\\username' 'smb://host.example.com/share/file.txt'", intern = TRUE)
或者,您可以调用system2()
,这样可以更安全地引用命令参数,并更好地处理跨平台的进程重定向:
contents <- system2('curl', c("-u", "domain\\\\username", "smb://host.example.com/share/file.txt"), stdout = TRUE)
curl 命令如果远程服务器要求密码,仍会提示我们输入。虽然我们可以使用
-u 'domain\\username:password'
指定密码来避免提示,但这样做会在命令字符串中暴露明文密码。为了更安全的方法,请阅读下面描述包的使用部分。
我们还可以向
curl 命令添加
-s
或
--silent
标志以抑制进度状态输出。请注意,这样做也将隐藏错误消息,因此我们可能还想添加
-S
(
--show-error
)。变量
contents
将包含文件行的向量,类似于
readLines("file.txt")
返回的值,我们可以使用
paste(contents, collapse = "\n")
将其压缩回去。
cURL API
虽然这一切都可以正常工作,但是我们可以通过使用专用的 cURL 库来改进这种方法。这个
curl package 提供了 R 绑定到
libcurl,这样我们就可以直接在程序中使用 cURL API。首先我们需要安装该软件包:
install.packages("curl")
require("curl")
(Linux用户需要安装libcurl开发文件。)
然后,我们可以使用curl_fetch_memory()
函数将远程文件读入变量中:
handle <- new_handle()
handle_setopt(handle, username = "domain\\username")
handle_setopt(handle, password = "secret") # If needed
request <- curl_fetch_memory("smb://host.example.com/share/file.txt", handle = handle)
content <- rawToChar(request$content)
首先,我们创建一个 "handle" 来配置请求,通过设置所需的任何身份验证选项。然后,我们执行请求并将文件内容分配给变量。如示,如果需要,请设置 "password" CURLOPT。
要处理类似于使用 "read.csv()" 的远程文件,我们需要创建一个流连接。 "curl()" 函数创建一个连接对象,我们可以使用它来通过任何支持标准 "url()" 函数返回的参数的函数来流式传输文件内容。例如,这是一种以 CSV 格式读取远程文件的方法,就像在问题中一样:
handle = new_handle()
...
stream <- curl("smb://host.example.com/share/file.txt", handle = handle)
contents <- read.csv(stream)
当然,上述描述的概念适用于通过cURL支持的
任何协议获取内容或响应正文,而不仅仅是SMB/CIFS。如果需要,我们还可以使用这些工具将文件下载到文件系统中,而不仅仅是将内容读入内存中。
/Volumes/lastdirectoryinfilepath/filename.csv
可以工作了 - 路径中的smb://educ-srvmedia1.campusad.msu.edu/...
部分是不必要的。 - Joshua Rosenbergsystem("net use /user:domain\\username \\\\host.example.com\\share")
- Cy Rossignol