What is an idiomatic Julia code for file I/O with exceptions handled?

question

#1

What is an idiomatic Julia code for tryOpen function below, which tests if 2 files can be opened and handles all exceptions? I’m looking for code replacing the comments or totally different code structure, if needed.

function tryOpen(fileName1, fileName2)
    try
        f1 = open(fileName1)
        f2 = open(fileName2)
        println("$fileName1 and $fileName2 can be opened")
    catch
        #print open file names
    finally
        #close opened files
    end
end

#2

If you want to just open and then (if successful) immediately close the file, you can do open(f->nothing, filename). This is equivalent to

open(filename) do f
    nothing
end

which ensures that the file is closed immediately (as opposed to waiting until garbage-collection happens). Or you can pass any other do-nothing function for the first argument, e.g. open(identity, filename)

Putting it together, you can do:

function isopenable(filenames)
    try
        open(identity, filename)
        return true
    catch
        return false
    end
end

To try multiple filenames, I would normally suggest just isopenable(filename1) && isopenable(filename2), though of course you could define

isopenable(filenames...) = all(isopenable, filenames)

#3

(Note that there is a built-in function isfile if you just want to check whether a file exists, or alternatively isfile(filename) || islink(filename), and you can check uperm(filename) for read permissions.)


#4

This code will throw uncatched exception when file doesn’t exist.

My question is about acquiring/opening a group of resources, which may throw an exception. I would like to know in catch and finally blocks, which ones were safely opened. This can be done with a bunch of extra status variables, one per resource, but I wonder if there is a way to avoid them. File opening is just an example of acquiring a resource.


#5

That’s why I put it in a try block.

Normally when you acquire a resource, you will associate some kind of handle object with it, e.g. an IOStream object for opening a file. You could always initialize these handles to some sentinel value, e.g. IOStream(""). In the catch block, you will know if they were successfully opened if they are different from the sentinel value.


#6

Thanks, that’s what I was looking for. Beginner’s problem.


#7

To avoid confusing the code reader (and allocating an unnecessary object), I recommending using a sentinel singleton value like nothing.