使用R以"smb://"开头读取远程文件

Jos*_*erg 20 smb r remote-access

要读入文件R,我通常会执行以下操作:

read.csv('/Users/myusername/myfilename.csv')
Run Code Online (Sandbox Code Playgroud)

但是,我正在尝试读取位于远程服务器上的文件(Windows SMB/CIFS共享),我通过FinderGoConnect to Server菜单项在我的Mac上访问该文件.

当我查看文件的属性时,文件路径与我习惯的不同.不是以:开头/Users/myusername/...,而是smb://server.msu.edu/.../myfilename.csv.

尝试阅读该文件,我尝试了以下内容:

read.csv('smb://server.msu.edu/.../myfilename.csv')
Run Code Online (Sandbox Code Playgroud)

但是,这没有用.

而不是通常的"没有这样的文件或目录"错误,这返回:

smb://server.msu.edu /.../ myfilename.csv在当前工作目录中不存在

我想文件路径需要不同的格式,但我无法弄清楚是什么.

你怎么能读到这种类型的文件R

sta*_*cks 18

说明

smb://educ-srvmedia1.campusad.msu.edu/... 实际上是一个URL而不是文件路径.

让我们打破这个

smb://表示使用服务器消息块协议(文件共享)

educ-srvmedia1.campusad.msu.edu 是服务器的名称

/.../myfilename.csv 是远程服务器上的文件共享/路径

您可以使用OSX上的Finder导航到此目录,因为它内置了对SMB协议的支持.Finder使用URL连接到远程服务,并允许您浏览文件.

但是R不了解SMB协议,因此无法正确解释文件路径.

R函数在内部read.csv()使用file(),请参阅https://stat.ethz.ch/R-manual/R-devel/library/base/html/connections.html

url和文件支持URL方案file://,http://,https://和ftp://

因此,R返回"无法找到文件"消息,因为无法找到该文件,因为协议不受支持.是的,有点混乱.

固定

您需要在本地文件系统上挂载文件共享.

所有这些意味着SMB协议的细节将由OS在幕后处理,文件共享将显示为本地目录.

这将允许R(和其他程序)处理远程文件的所有意图和目的,就像任何其他本地文件一样. 此讨论显示了这样做的一些选项.

例如

# need to create /LocalFolder first
mount -t cifs //username:password@hostname/sharename /LocalFolder
Run Code Online (Sandbox Code Playgroud)

然后在R:

read.csv('/LocalFolder/myfilename.csv')
Run Code Online (Sandbox Code Playgroud)

额外

Windows用户可以使用UNC路径更轻松地完成此操作
如何从R中的UNC指定目录中读取文件?


Cy *_*nol 10

TL; DR

这是一种使用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)
Run Code Online (Sandbox Code Playgroud)

如果我们需要将内容读取为CSV,就像在问题中一样,我们可以通过另一个函数来传输文件:

> stream <- curl("smb://host.example.com/share/file.txt", handle = handle)
> contents <- read.csv(stream)
Run Code Online (Sandbox Code Playgroud)

让我们看一下通过smb:// URL 访问远程文件的更健壮的方法,除了安装远程文件系统的其他答案中描述的方法.不幸的是,我对这个有点晚了,但我希望这有助于未来的读者.

在某些情况下,我们可能没有安装文件系统所需的权限(这需要在许多系统上进行管理或root访问),或者我们可能根本不想仅仅为了读取单个文件而安装整个文件系统.我们将使用cURL库来读取文件.这种方法提高了程序的灵活性和可移植性,因为我们不需要依赖外部安装的文件系统的存在.我们将研究两种不同的方式:通过system()调用,以及使用提供cURL API的包.

一些背景:对于那些不熟悉它的人,cURL提供了用于通过各种协议传输数据的工具.从版本7.40开始,cURL支持通常用于Windows文件共享服务的SMB/CIFS协议.cURL包含一个命令行工具,我们可以使用它来获取文件的内容:

$ curl -u 'domain\username' 'smb://host.example.com/share/file.txt'
Run Code Online (Sandbox Code Playgroud)

上面的命令从远程服务器host.example.com读取并输出(到STDOUT)file.txt的内容,该文件作为域上的指定用户进行身份验证.如果需要,该命令将提示我们输入密码.如果我们的网络不使用域,我们可以从用户名中删除域部分.

系统调用

我们可以使用以下system()函数在R中实现相同的功能:

system("curl -u 'domain\\username' 'smb://host.example.com/share/file.txt'")
Run Code Online (Sandbox Code Playgroud)

请注意双反斜杠domain\\username.这会转义反斜杠字符,以便R不会将其解释为字符串中的转义字符.我们可以通过将函数的intern参数设置system()TRUE:将命令输出中的文件内容捕获到变量中:

contents <- system("curl -u 'domain\\username' 'smb://host.example.com/share/file.txt'", intern = TRUE)
Run Code Online (Sandbox Code Playgroud)

...或者通过调用system2()来引用命令参数以获得安全性并更好地处理平台之间的进程重定向:

contents <- system2('curl', c("-u", "domain\\\\username", "smb://host.example.com/share/file.txt"), stdout = TRUE)
Run Code Online (Sandbox Code Playgroud)

卷曲如果需要远程服务器的命令仍然会提示我们输入密码.虽然我们可以使用指定密码-u 'domain\\username:password'来避免提示,但这样做会在命令字符串中公开明文密码.有关更安全的方法,请阅读下面介绍软件包使用情况的部分.

我们还可以在curl命令中添加-s--silent标记以禁止进度状态输出.请注意,这样做也会隐藏错误消息,因此我们也可能还想添加().该变量将包含文件行的向量 - 类似于我们可以使用返回的值返回的值.-S--show-errorcontentsreadLines("file.txt")paste(contents, collapse = "\n")

cURL API

虽然这一切都很好,但我们可以通过使用专用的cURL库来改进这种方法.这个curl包提供了与libcurl的 R绑定,因此我们可以直接在程序中使用cURL API.首先我们需要安装包:

install.packages("curl")
require("curl")
Run Code Online (Sandbox Code Playgroud)

(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)
Run Code Online (Sandbox Code Playgroud)

首先,我们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)
Run Code Online (Sandbox Code Playgroud)

当然,上述概念适用于通过cURL支持的任何协议获取内容或响应主体,而不仅仅是SMB/CIFS.如果需要,我们也可以使用这些工具将文件下载到文件系统,而不是仅仅将内容读入内存.


eip*_*i10 5

下面我展示了一种我不时用来从SMB网络驱动器读取数据的方法.在下面的代码中,我使用R system函数从R内部执行所有操作,但您也可以从OSX命令行或使用Command-K(连接到服务器)从Finder中安装驱动器:

如果您还没有,请在本地驱动器上创建共享所在的目录(这不是必需的,因为您可以将驱动器安装在现有位置):

system("mkdir /Users/eipi10/temp_share/")
Run Code Online (Sandbox Code Playgroud)

要么

dir.create("/Users/eipi10/temp_share/")
Run Code Online (Sandbox Code Playgroud)

将网络驱动器安装到刚刚创建的文件夹中.在下面的代码中,//username@domain.address.edu/home/u/eipi10是您的用户名和SMB共享的地址.

system("mount_smbfs //username@domain.address.edu/home/u/eipi10 /Users/eipi10/temp_share")
Run Code Online (Sandbox Code Playgroud)

如果有密码验证,那么也可以包含密码:

system("mount_smbfs //username:password@domain.address.edu/home/u/eipi10 /Users/eipi10/temp_share")
Run Code Online (Sandbox Code Playgroud)

阅读数据:

dat = read.csv("/Users/eipi10/temp_share/fileToRead.csv")
Run Code Online (Sandbox Code Playgroud)

在R中,您还可以以编程方式选择要读取的文件:

data.list = lapply(list.files(pattern="csv$", "/Users/eipi10/temp_share/", full.names=TRUE), read.csv)
Run Code Online (Sandbox Code Playgroud)