6

Can File.ReadAllBytes cause IOException when it is called twice without enough interval between the calls?

When I set Row and Col of grid, it fires RowColChange event. The RowColChange has some code which opens the same file by using File.ReadAllBytes. I understand that ReadAllBytes internally uses using on FileStream so the filestream is closed after being used. But is it possible to have some delay in telling operating system that file is released so the subsequent usage of File.ReadAllBytes could fail and throw an exception. Any thoughts? Thank you!

grid.Row = 0
grid.Row = 1
grid.Col = 3


Private Sub grid_RowColChange(ByVal sender As Object, ByVal e As System.EventArgs) Handles grid.RowColChange
    'Is it possible to get IOException saying the process can't access the file because it is being used by another process.
     Display(File.ReadAllBytes(filePath))
End Sub
Alessandro D'Andria
  • 8,663
  • 2
  • 36
  • 32
Jyina
  • 2,530
  • 9
  • 42
  • 80
  • 2
    [reference source](https://referencesource.microsoft.com/#mscorlib/system/io/file.cs,920) suggests "no": `ReadAllBytes` opens the file with `FileShare.Read`, which is documented as "Allows subsequent opening of the file for reading". Are you sure there are no concurrent writes? – Cee McSharpface Mar 14 '17 at 19:19
  • so many examples on how to do this on the internet as well as `stackoverflow` http://stackoverflow.com/questions/35307459/cannot-open-a-file-used-by-another-process – MethodMan Mar 14 '17 at 19:20
  • @dlatikay, there are no writes at all to the file. Thanks for clarifying the usage of ReadAllBytes. Since I have no evidence of the file being used by another process, I am just trying to eliminate some scenarios. – Jyina Mar 14 '17 at 19:36
  • @dlatikay What does though the "//Do a blocking read" comment mean in the InternalReadAllBytes? – Mircea Ion Aug 13 '18 at 19:29
  • `ReadAllBytes` doesn't support `FileShare`. Try it yourself by opening a .csv file with Microsoft Excel then use c# to read this file. – Ray Chakrit Mar 11 '23 at 14:38

2 Answers2

5

Please try the following:

Using fileStream = New FileStream("path", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
    Using streamReader = New StreamReader(fileStream)
        Dim content = streamReader.ReadToEnd()
    End Using
End Using

It is actually possible that two threads read from the same file at the same file, please try to use the code above to read the file.

Snicker
  • 957
  • 10
  • 16
  • 1
    That's pretty much the same as using `File.ReadAllBytes`. If something is locking the file completely then you can't open it either way you do it. – Visual Vincent Mar 14 '17 at 20:33
  • 3
    @VisualVincent yes, I know that there isn't a huge different, but the important difference is that this also allows another thread/program to write while you are reading (check out the reference source: http://referencesource.microsoft.com/#mscorlib/system/io/streamreader.cs,fc51cfc8975d71a1) I thought that maybe that would help, but you are right, when he doesn't write that's rather useless. – Snicker Apr 19 '17 at 13:47
  • I hadn't though of that, though `File.ReadAllBytes()` already specifies `FileShare.Read` (see the other answer to this question) so the problem is that something else is locking the file completely. – Visual Vincent Apr 19 '17 at 14:12
  • @VisualVincent (I know it's three years since), but the BIG difference is that the code above uses `FileShare.ReadWrite` (allow other processes to read and write), not `FileShare.Read` (prohibit other processes to write). Which is why the approach here works as a workaround. – Abel Dec 08 '20 at 10:53
  • @Abel The thing is that if another thread/process is already locking the file without specifying `FileShare.Read`, then there's no way to change the code in the question to make it work. The OP uses `File.ReadAllBytes()` which opens the file with `FileShare.Read`. Since all that method ever does is _read_, switching to a method that specifies `FileShare.ReadWrite` won't make a difference since the OP doesn't use the `Write` part. – Visual Vincent Jan 17 '21 at 22:28
  • 2
    @VisualVincent, actually, it does. If a different program opens for read/write (like: Excel opening an Excel file), and you try to read it with `File.ReadAllBytes()`, it will fail. Open it with `FileShare.ReadWrite` will, however, succeed: it allows another program to have the file open for writing, and still read it with your program. I use it for exactly that: reading Excel files that are open in Excel, but the same applies to many other applications. – Abel Jan 20 '21 at 18:31
  • @Abel Interesting, I hadn't considered that scenario. It makes sense now that you mention it, as `File.ReadAllBytes()` tries to open it exclusively with only `Read` share whilst another program already has it open with `ReadWrite`. – Visual Vincent Feb 13 '21 at 12:18
5

Building on this answer and the fact that File.ReadAllBytes uses the FileShare.Read flag in combination with FileAccess.Read (reference), concurrent calls to File.ReadAllBytes on the same file would never throw the "used by another process" IOException, unless another process already has it open with a write lock - FileShare.Read denies writing and would therefore fail.

If you see the exception because of concurrent writes, then yes, you have options:

  1. wait and retry. There is good coverage on this approach here on SO, for example this one

  2. Open a FileStream and specify FileShare.ReadWrite, as detailed here

Community
  • 1
  • 1
Cee McSharpface
  • 8,493
  • 3
  • 36
  • 77