{"id":24713,"date":"2007-10-23T10:00:00","date_gmt":"2007-10-23T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/10\/23\/superstition-why-is-getfileattributes-the-way-old-timers-test-file-existence\/"},"modified":"2007-10-23T10:00:00","modified_gmt":"2007-10-23T10:00:00","slug":"superstition-why-is-getfileattributes-the-way-old-timers-test-file-existence","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20071023-00\/?p=24713","title":{"rendered":"Superstition: Why is GetFileAttributes the way old-timers test file existence?"},"content":{"rendered":"<p>If you ask an old-timer how to test for file existence, they&#8217;ll say, &#8220;Use <code>GetFileAttributes<\/code>.&#8221; This is still probably the quickest way to test for file existence, since it requires only a single call. Other methods such as <code>FindFirstFile<\/code> or <code>CreateFile<\/code> require a separate <code>FindClose<\/code> or <code>CloseHandle<\/code> call, which triggers another network round-trip, which adds to the cost.\n But back in the old days, the preference for <code>GetFileAttributes<\/code> wasn&#8217;t just a performance tweak. If you tried to open the file to see if it existed, you could get the wrong answer!\n Some network providers had a feature called a &#8220;data path&#8221;. You can add directories to the data path, and if any attempt to open a file failed, the network provider would try again in all the directories in the data path. For example, suppose your data path was <code>\\\\server1\\backups\\dir1;\\\\server1\\backups\\dir2<\/code> and you tried to open the file <code>File.txt<\/code>. If the file <code>File.txt<\/code> could not be found in the current directory, the network provider would try again, looking for <code>\\\\server1\\backups\\dir1\\File.txt<\/code>, and if it couldn&#8217;t find that file, it would try again with <code>\\\\server1\\backups\\dir2\\File.txt<\/code>.\n All this extra path searching happened behind Windows&#8217;s back. Windows had no idea it was happening. All it knew is that it issued an open call, and the open succeeded.\n As a result, if you used the &#8220;open a file to see if it exists&#8221; algorithm, you would get the wrong result for any file that existed on the data path but not in the current directory. These network providers didn&#8217;t search the data path in response to <code>GetFileAttributes<\/code>, however, so a call to <code>GetFileAttributes<\/code> would fail if the file didn&#8217;t exist in the current directory, regardless of whether it existed on the data path.<\/p>\n<p> I don&#8217;t know if any network providers still implement this data path feature, but Windows code in general sticks to <code>GetFileAttributes<\/code>, because it&#8217;s better to be safe than sorry. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you ask an old-timer how to test for file existence, they&#8217;ll say, &#8220;Use GetFileAttributes.&#8221; This is still probably the quickest way to test for file existence, since it requires only a single call. Other methods such as FindFirstFile or CreateFile require a separate FindClose or CloseHandle call, which triggers another network round-trip, which adds [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[2],"class_list":["post-24713","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>If you ask an old-timer how to test for file existence, they&#8217;ll say, &#8220;Use GetFileAttributes.&#8221; This is still probably the quickest way to test for file existence, since it requires only a single call. Other methods such as FindFirstFile or CreateFile require a separate FindClose or CloseHandle call, which triggers another network round-trip, which adds [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/24713","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=24713"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/24713\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=24713"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=24713"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=24713"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}