That's not what I wrote. I said there's no _built-in_ way to check existence of the file. A reasonable interpretation of "built-in" is for an obvious named function such as "File.exists()" _without_ cobbling together extra workarounds and hacks -- whether those workarounds include re-purposing other VB built-in functions with On Error ... or using Win32 interop.
> in VB, [...] would at worse be comprised of a exception handler (on error ...)
That's an example of what I meant of not being built-in to VB. I should have been more clear. We were using different meanings of "builtin".
In any case, the following "pure" VB code to check for file existence is not found on Google or Bing search but I still have it from my 1995 archives and copied it here. It has many lines of code (instead of a simple "one-liner") because it tries to cover all the edge cases. And yet with all that defensive code, there's still a hidden timebomb of a bug in it. Can anyone spot it? The code is unmodified from Visual Basic Programmer's Journal. In contrast, the alternative using Win32 interop with OF_EXISTS doesn't have the bug.
Dim strTestFilename As String
strFilename = Trim(strFilename)
' To avoid problem with known bug, don't pass root directory to
' the Name function
Select Case Right$(strFilename, 1)
Case "\": strExistsFilename = "Root": Exit Function
Case "\.": strExistsFilename = "Root": Exit Function
Case "\..": strExistsFilename = "Root": Exit Function
End Select
On Local Error Resume Next ' Enable error trapping for Name function
Name strFilename As strFilename ' A trick to see if filename/path is good
' Now check the resulting err code of the Name function
Select Case Err
Case 5 ' Illegal function call
Case 53 ' File not found
Case 58 ' File exists (maybe)
strTestFilename = Dir$(strFilename)
If Len(strTestFilename) Then
strExistsFilename = "" ' It's a file
Exit Function
Else
strExistsFilename = "Dir" ' It's a directory
Exit Function
End If
Case 64 ' Bad filename
Case 68 ' Device unavailable
Case 71 ' Disk not ready
Case 75 ' Access denied
Case 76 ' Path not found
End Select
My point was that C# builtin File.Exists() is a lot simpler than that.Your code sample renames the file, then globs anyway (when dir$ by itself can also be used to check existence). It looks too convoluted, and I cannot imagine why it needs to be so.
What is exactly the corner case that you want to avoid -- and if such case really exists, why are you so sure the File.Exists() implementation would not fall into the same pit trap, considering it also simply uses the metadata?
Disclaimer: I'm only familiar with VBA, not VB itself. But these file metadata functions definitely already exist in 95's VB5. (EDIT: Actually 97's. Maybe the problem is these functions did not exist in earlier VBs? But I would find it hard to imagine you could not check a file's size).
The sample code smells even in the trivial-case checks. E.g. Right$(_, 1) will only return a 1-char string at most, yet it tries to compare it with 2, 3 len strings. I didn't check any further than that.
Function FileExists(Filename) As Boolean
On Error Resume Next
FileExists = (GetAttr(Filename) And vbDirectory) = 0
End Function
It's not 2 lines, but it's 4, including function header. All functions used are available at least since 16-bit VB3. Is this what you call "a workaround and a hack?". It's practically the same thing .NET is doing for File.Exists() (or at least the current one -- dunno what .NET 1 was doing), so I cannot think of any gotchas that would affect this but not File.Exists.Another way, use Dir by itself. This is even mentioned in the VB docs...
FileExists = Dir(Filename) <> ""
3 lines. It also ignores directories. Sure, this has problems with wildcards, but so does your example, and that's another oneliner to fix, using Replace$ (as wildcards are not legal characters in filenames in win32, either way). And if Dir("\") returns true for some reason, I guess that's a runtime bug, which is pretty valid criticism, even if a bit of a corner case (who really wants to check if "\" exists?). I would prefer the first version anyway.I still stand by my original point that this is a very poor example, since there are a million ways check for a file's existence, many using only builtin functions of the language. You can certainly find nigh-overcomplicated ways to do so, apparently even on books, but ... why? Not a fan of cargo-culting like this; it tends to create Cherteston's fences.
Many languages also lack a direct "File_Exists" function (e.g. Lua comes to mind) since it's about the most trivial thing to implement (and a magnet for TOCTOU issues). Or even if they do come with such function, it does not distinguish directories from files (e.g. Tcl). I hardly think the lack of a "file_exists" function discriminates anything in language design, modern or otherwise.
Tcl has the built-in functions [file exists], [file isdirectory] and [file isfile] to serve your existence-checking needs.
GP complains that there is no direct function for "file exist". And technically there is not on Tcl either because file exists cmd will return true for directories. You can trivially build your proc that specifically checks for files (it will likely use isfile) but that is exactly the point of my comment. I have shown how do that for VB and it is not far from a one liner.
Presence/absence of a file exists function is a very poor example. If the language didn't allow you to check e.g. if a file was a directory or not, then GP might had have a point. But this is not the case.
I am not sure if I'm getting my point clear. I'm presuming you are trying to defend that yes, you can check if a file exists in Tcl, even if there's no specific function for it, but that is, again, exactly my point. Like what you're doing, I've shown many ways to do it in VB.
I guess the fact that someone needs to nitpick me in exactly the same way I was nitpicking the GP is quite the proof that the analogy works perfectly...
exists followed by open is a pointless exists because anything can happen in between.
Conversely, if you are neither the producer nor consumer of the file at this time, you don't want to actually open it just as a way to stat it, because actually opening it updates it's access time and interferes with the actual consumer(s). Even read-only non-exclusive.
I thought you were saying you could use a seperate lock to guard the time between exist() and open(), which is possible but silly.
Now I'm not sure what you meant. Is "it" exists() or open()? You can use open() as a lock for other things. It doesn't need any other locks itself. You can't use exists() as a lock.
Or, I guess you are saying one process can open the file and others can merely check exists()? Yes depending on what the purpose was, what you intend to do with the results of exists(), because it isn't true any more the instant after exists() returns, only while exists() is actually running.
That makes it sound useless and therefor what is the problem that VB6 didn't have it? That might very well be why it was omitted.
But you do need some form of stat(), a way to get info about files without affecting them in any way. A process needs to be able to watch a files access time to know if it's been accessed yet, or when last, without that very observation changing the access time or making the file appear open()ed to other processes that may care about that. Even being opened read-only andbnon-exclusive is still opened. Another process may need to know that it has eclusive access or else it can't do it's thing, so it will fail it's own open() exclusive.
Even if the other process retries and open succeeds a few cycles later, changing the access time breaks the process that's waiting for the file to be accessed by it's actual consumer so it can be automatically deleted for example, or simply logged the fact that the customer has downloaded the edi file, the remote client/browser has loaded the temp file, someone somewhere has accessed super secret file, etc.
(setting aside that these days at least on *ix you frequently disable atime updates in the filesystem altogether and just do not build anything on top of that any more for performance and flash write life reasons. But I have processes that use it only in tmpfs in ram even while it's off for the real filesystem.)
If you actually open a file, you update it's access time, and you interfere with the process that should actually open the file. Those both break perfectly simple business logic.
If you want to get the access time, why don't you just query the access time? Which is likely the only thing almost universally guaranteed not to change it... And I'm sure VB6 has an API for that, considering that VBA had a global API for it (FileDateTime).
(Which is, btw, yet another way to one-line check if a file exists).
The way you probably did in your now-deleted comment claiming that stat() updated atime?
Citation needed. https://learn.microsoft.com/en-us/dotnet/api/system.io.file.... doesn't warn of any such thing.
No.
> Citation needed. https://learn.microsoft.com/en-us/dotnet/api/system.io.file.... doesn't warn of any such thing.
https://learn.microsoft.com/en-us/windows/win32/api/winbase/...
OF_EXIST: Opens a file and then closes it.
OpenFile() opens the file??? c'est incroyable!
OF_EXISTS is just a side effect of some actual operation. It's some related info you you get along the way. You would not use that as the way to only check the file. Holy cow. Please do continue trying to spread the wisom.
> In fact, I imagine File.Exists()/OF_EXISTS also opens the file (then immediately closes it).
I never said any such thing.
Yet another trivially verified false statement. Fits the pattern.
If you didn't say any such thing, then why did you bother countering my comment at https://news.ycombinator.com/item?id=42107195 ? Aha! Gotcha!
I never said, either explicitly nor implicitly, that File.Exists() modifies access time.
There is nothing there in that comment nor it's parent.
OF_EXISTS is not a thing by itself. It does not "open a file and then close it" which is a ridiculous and incorrect thing you DID actually say. OF_EXISTS is just a bitmask flag that can be returned by several functions, including ones that open files.
You have said a continuos string of incorrect things and employed invalid logic this whole time, and this yet again fits.
correction: you said opens a file and closes it about OF_EXIST the bitmask flag to tell OpenFile() how you want to open it. Slightly less ridiculous, yet still not a thing that opens a file, OpenFile() opens the file.