2

I have a flexdashboard which is used by multiple users. They read, modify and write the same (csv) file. I haven't been able to figure out how to do this with a SQL connection so in the meantime (I need a working app) I would like to use a simple .csv file as a database. This should be fine since the users aren't likely to work on it the exact same time and loading and writing the full file is almost instant.

My strategy is therefore:

1-load file,

2-edit (edits are done in rhandsontable which is backconverted to a dataframe)

3-save: (a)-loads file again (to get the latest data), (b)-appends the edits from the rhandsontable and keeps the latest data (indicated by a timestamp) (c)-write.csv

I'm thinking I should add something in (1) such that it checks if the file is not already in use/open (because an other user is at (3). So: check if open, if not-> continue, else-> sys.sleep(3) and try again.

Any ideas about how to do this in R? In Delphi it would be something like: if fileinuse(filename) then sleep(3) else df<-read.csv

What's the R way?

halfer
  • 19,824
  • 17
  • 99
  • 186
Algomas
  • 61
  • 7

2 Answers2

0

Edit:

I'm starting with the my edited answer as it's more elegant. This uses a shell command to test whether a file is available as discussed in this question:

How to check in command-line if a given file or directory is locked (used by any process)?

This avoids loading and saving the file, and is therefor more efficient.

# Function to test availability
IsInUse <- function(fName) {
  shell(paste("( type nul >> ", fName, " ) 2>nul && echo available || echo in use", sep=""), intern = TRUE)=="in use"
}

# Test availability
IsInUse("test.txt")

Original answer:

Interesting question! I did not find a way to check if a file is in use before trying to write to it. The solution below is far from elegant. It relies on a tryCatch function, and on reading and writing to a file to check if it is available (which can be quite slow depending on your file size).

# Function to check if the file is in use (relies on reading and writing which is inefficient)
IsInUse <- function(fName) {
  rData <- read.csv(fName)
  tryCatch(
    {
      write.csv(rData, file=fName, row.names = FALSE)
      return(FALSE)
    },
    error=function(cond) { 
      return(TRUE)
    }
  )
}

# Loop to check if file is in use
while(IsInUse(fName)) {
  print("Still in use")
  Sys.sleep(0.1)
}
# Your action here

I also found the answer to this question useful How to write trycatch in R to make sense of the tryCatch function.

I'd be interested to see if anyone else has a more elegant suggestion!

MatAff
  • 1,250
  • 14
  • 26
  • 1
    Thanks MatAlf! I can work with that in the mean time. I'm still hoping for more elegant solution though so I'm not flagging as "answered" just yet. – Algomas Nov 03 '18 at 08:17
  • I've also tried using: assertthat::is.writeable(path) but that gives "TRUE" whether the file is either open or closed :-( – Algomas Nov 06 '18 at 14:52
  • One more thing: the solution given by MatAff works fine on windows but when, as in my case, the Rserver runs on a linux machine the app breaks. One option is to re-write for linux, the other is to use a try(catch as such: counter <- 0 while(counter<5) { tryCatch({write.xlsx(finalDF, fName); break}, error = function (e) {}, warning = function (w) {} ) Sys.sleep(1) counter <- counter + 1 } – Algomas Nov 14 '18 at 12:02
-1

Interesting question, indeed! Curious about an elegant solution too...

JohnDoedel
  • 131
  • 1
  • 10