rfile-in-use

import file when not in use (any more)


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?


Solution

  • 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!