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

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
1 Like

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 Likes

(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.)

2 Likes

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.

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.

2 Likes

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

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

1 Like

Where in Julia"s official docs may the answer to OP"s essential question be found?
Thank you.

https://docs.julialang.org/en/v1/manual/control-flow/#The-try/catch-statement

But please consider not reviving ancient topics without a good reason.

Sorry, but cannot even find half of the content posted above.

1 Like