我需要使用我的Shiny应用程序读取一个非常大的固定宽度文件。我的程序当前结构的方式是ui.R包含一个fileInput,允许用户使用浏览器找到该文件。
在服务器端,我只捕获文件的路径,如下所示:
path2file <- reactive({
infile <- input$path2file
if (is.null(infile)) return(NULL)
infile$datapath
})
后续函数将该路径作为输入,并根据其布局规范读取文件。这一切都很好;但是当处理非常大的fwf文件时,我的程序运行速度极慢,需要花费数小时才能使用fileInput获取文件的路径名
我怀疑fileInput实际上是在整个文件中读取,然后我的函数只返回数据路径,即使我没有明确地读取函数中的任何文件格式类型。
我的目标是继续使用我现在构建的程序,并使用我的fileInput仅获取此文件的路径。我在SO上找到了这个主题,看到它是一个可能的选择。
Getting file path from Shiny UI (Not just directory) using browse button without uploading the file
但是,我还打算尽量减少我拥有的包依赖项的数量;这已成为一个大问题,所以如果我必须使用额外的包,我会,但我想不惜一切代价避免这种情况。
我尝试了这个便宜的技巧:
path2file <- reactive({
infile <- input$path2file
if (is.null(infile)) return(NULL)
scan(infile$datapath, n = 1)
infile$datapath
})
认为这将是一个快速的解决方法,但它也非常慢,所以我怀疑它也不是只读n = 1.所以,我的问题是任何人都可以找到一种方法使用fileInput允许用户定位文件并让服务器端函数仅捕获路径而不读取文件或尝试以任何方式解析它?更重要的是,这可以使用基本R和Shiny中的函数来完成,而不必从其他扩展包中获取函数吗?
以上是server.R文件中代码的相关部分以及ui.R文件中相关的代码部分
fileInput('path2dor', 'Choose the DOR .txt file to format',
accept=c('text/csv',
'text/comma-separated-values,text/plain', '.csv')),
谢谢你的建议。
答案 0 :(得分:0)
fileInput
无法使用此功能。原因是因为出于安全原因,“ fileInput”不向服务器提供本地路径信息。
使用fileInput
,用户可以在其本地计算机上的浏览器中导航,服务器端生成的文件就是所选本地的一次上传副本。
您也可以使用shinyFiles
程序包,该程序包确实会在服务器端进行导航。这意味着,您可以在本地计算机上获得所有路径。
第二种选择可能是简单的文本输入,它允许用户手动添加路径(确保检查服务器端的路径以免遇到任何麻烦)。
答案 1 :(得分:0)
正如其他人所指出的,由于安全问题,shiny 创建了一个 tmp 文件夹,其中所有加载的文件都使用 fileinput
因此,您需要选择文件夹中所有感兴趣的文件,然后使用 ...$datapath
调用此 tmp 文件
但是请注意,datapath
的每个元素都将包含目录信息和相应的文件名。因此,您需要修剪这些路径以仅考虑 tmp 目录。这可以通过以下方式实现...
假设您将创建一个名为 phu
的对象,该对象将仅包含您使用 input$upload$datapath[1]
fileInput("upload", NULL, buttonLabel = "Upload...", multiple = TRUE)
)
phu<-as.character(input$upload$datapath[1])
phu<-substr(phu,1,nchar(phu)-5)
第二行删除字符串中的最后五个字符。这些字符是 0.txt
或您在输入中调用的任何其他扩展名。提供的代码仅适用于 .txt
文件并且需要 tm
包。您现在可以使用对象 phu
作为感兴趣的输入目录。
最后,您需要使用 output
对象调用此输出并将其打印在您的 ui
中,如下面的 textOutput("Pdiretory")
所示。
下面的例子展示了整个过程。请注意,没有安全问题,因为此临时文件及其内容将在关闭时被删除。同样,输入文件是 .txt
文件。
library(shiny)
library(tm)
ui <- fluidPage(
fileInput("upload", NULL, buttonLabel = "Upload...", multiple = TRUE),
textOutput("Pdiretory")
)
server <- function(input, output, session) {
listdir <- eventReactive(input$upload, {
phu<-as.character(input$upload$datapath[1])
phu<-substr(phu,1,nchar(phu)-5)
txt<-Corpus(DirSource(phu),readerControl = list(language = "en"))
print(txt)
})
output$Pdiretory <- renderPrint ({
listdir()
})
}
shinyApp(ui = ui, server = server)