Reading big files while file may be still copying into the folder

Naomi Nosonovsky 7,856 Reputation points
2020-12-07T23:28:47.18+00:00

Hi everybody,

We seem to be getting an error on a regular basis at the same time. The error occurs when we try to read the file and when we check properties of that file in the Windows Explorer we can see that there are 2 dates: Creation Date and Modification Date which are several seconds apart and the error occurs exactly in between these two.

I am wondering what code should I implement in order to re-try? E.g. if I add code such as

internal bool FileIsReadyToProcess(string fullPathFileName)
        {  
            int iCount = 0;
            bool isValid = false;
            do
            {
                isValid = File.Exists(fullPathFileName);
                if (!isValid) Thread.Sleep(this.intWaitForFileTime);
            } while (!isValid && iCount++ < this.intFileReadingAttempts);
            return isValid;
        }

would this be sufficient to prevent these situations? E.g. is it enough to use File.Exists or I need to make different test?

Thanks in advance.

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,904 questions
0 comments No comments
{count} votes

4 answers

Sort by: Most helpful
  1. Timon Yang-MSFT 9,591 Reputation points
    2020-12-08T03:26:51.373+00:00

    If you are to judge whether the file has been pasted, is the following method possible?

            private static bool IsFileLocked(FileInfo file)  
            {  
                FileStream stream = null;  
                try  
                {  
                    stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);  
                }  
                catch (IOException)  
                {  
                    return true;  
                }  
                finally  
                {  
                    if (stream != null)  
                        stream.Close();  
                }  
                return false;  
            }  
           static void Main(string[] args)  
           {  
               FileInfo fileInfo = new FileInfo(@"d:\test\psd7003.xml");  
               bool IsLocked = true;  
               while (IsLocked)  
               {  
                   IsLocked = IsFileLocked(fileInfo);  
                   Thread.Sleep(1000);  
               }  
           }  
    

    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    2 people found this answer helpful.

  2. Cheong00 3,476 Reputation points
    2020-12-08T06:05:55.463+00:00

    Agreed with Timon. It's better to just test it by try to open an exclusive read-write handle on file. If the file is still in use, it would simply fail.

    If you don't mind a bit of P/Invoke, you can try open the file with Generic_Read by CreateFile() API, then pass the handle to LockFileEx() with LOCKFILE_EXCLUSIVE_LOCK flag only, and it should wait indefinitely until the file write is completed and handle is closed. After that pass the handle to FileStream and you can resume normal .NET file processing. (Don't forget to put your CloseHandle() call on finally block or you'll leak handles.)

    1 person found this answer helpful.
    0 comments No comments

  3. Karen Payne MVP 35,421 Reputation points
    2020-12-08T01:25:32.267+00:00

    Hello @Anonymous

    Have you considered using a FileSystemWatcher where you can setup filtering and subscribe to OnChanged event along with others.

    Here is a basic example which has more than needed

    Source project
    .

    using System;  
    using System.Collections.Generic;  
    using System.IO;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
      
    namespace FileSystemWatcher1  
    {  
        public class WatchOperations : IDisposable  
        {  
            private string _folderName;  
            public readonly FileSystemWatcher FileSystemWatcher;  
      
            /// <summary>  
            /// Enable FileSystemWatcher to monitor folder  
            /// </summary>  
            public void EnableWatch() => FileSystemWatcher.EnableRaisingEvents = true;  
            /// <summary>  
            /// Disable FileSystemWatcher from monitor folder  
            /// </summary>  
            public void DisableWatch() => FileSystemWatcher.EnableRaisingEvents = false;  
      
            /// <summary>  
            /// Create a instance of FileSystemWatcher with filters  
            /// and events to react to file operations in path pasted in  
            /// to this constructor.  
            /// </summary>  
            /// <param name="path">Directory to monitor</param>  
            /// <param name="filter">File type defaults to .txt (text files)</param>  
            public WatchOperations(string path, string filter = "*.txt")  
            {  
                _folderName = path;  
      
                FileSystemWatcher = new FileSystemWatcher(path)  
                {  
                    Filter = filter,  
                    NotifyFilter =   NotifyFilters.LastAccess  
                                   | NotifyFilters.LastWrite  
                                   | NotifyFilters.FileName  
                                   | NotifyFilters.DirectoryName  
                      
                };  
      
                FileSystemWatcher.Changed += OnChanged;  
                FileSystemWatcher.Created += OnCreated;  
                FileSystemWatcher.Renamed += OnRenamed;  
      
            }  
            /// <summary>  
            /// Constructor to permit setting up as a private form or  
            /// class level property or variable  
            /// </summary>  
            public WatchOperations()  
            {  
                FileSystemWatcher = new FileSystemWatcher();  
            }  
            /// <summary>  
            /// Fired when a file is renamed  
            /// </summary>  
            /// <param name="sender"></param>  
            /// <param name="e"></param>  
            private void OnRenamed(object sender, RenamedEventArgs e)  
            {  
                Console.WriteLine($@"Rename: {e.OldName}, {e.Name}");  
            }  
            /// <summary>  
            /// Fired when a file is created  
            /// </summary>  
            /// <param name="sender"></param>  
            /// <param name="e"></param>  
            private void OnCreated(object sender, FileSystemEventArgs e)  
            {  
                Console.WriteLine($@"Created: {e.Name}");  
            }  
      
            private void OnChanged(object sender, FileSystemEventArgs e)  
            {  
                Console.WriteLine($@"Changed: {e.Name}");  
            }  
            /// <summary>  
            /// Destroy watcher which stops any watches  
            /// </summary>  
            public void Dispose()  
            {  
                FileSystemWatcher?.Dispose();  
            }  
        }  
    }  
    

  4. Karen Payne MVP 35,421 Reputation points
    2020-12-08T16:10:25+00:00

    @Anonymous

    I made a copy of my comment into an answer and hopefully this will get you on the right path.

    Check out the following code sample which I just created. Key code is here. The idea is to simulate copying from code other than yours and your code checking if the copy process has completed.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.