12
votes

Comment tester si un fichier est complètement copié dans .NET

Je surveille un dossier pour les nouveaux fichiers et devez les traiter. Le problème est que l'ouverture de fichier occasionnelle échoue, car le système n'a pas fini de copier.

Quelle est la bonne façon de tester si le fichier est terminé la copie?

Clarification: Je n'ai pas d'autorisations d'écriture dans le dossier / fichiers et je ne peux pas contrôler le processus de copie (c'est l'utilisateur).


2 commentaires

Bonne question! Quand j'ai eu ce problème, je viens d'ajouter System.threading.threading.thread.sleep (1000), mais je voudrais amour pour obtenir une meilleure solution (c'est juste si boiteux ...)


Avez-vous lu accès au fichier original, qui est copié?


9 Réponses :


0
votes

Une approche que je prends toujours est de créer un fichier à la fin de ma copie / transfert nommé "Token.txt" sans contenu. L'idée est que ce fichier sera créé à la fin de l'opération de transfert, vous pouvez donc surveiller cette création de fichier et lorsque ce fichier est créé, vous commencez à travailler avec vos fichiers. N'oubliez pas d'effacer ce fichier de jeton toujours lorsque vous commencez à traiter vos fichiers.


3 commentaires

Mais si le compte d'utilisateur n'a pas le droit de supprimer des fichiers dans le serveur, cette approche n'aurait aucune utilité.


Ne pense pas que l'extraire attend un processus de copie qu'il contrôle lui-même. Alors, il n'y aurait pas de fichier jeton, non?


Je pense que vous ne pouvez pas dire s'il a ou non accès / contrôle sans processus sans plus de détails. C'est comme un brainstorming où tout le monde donne des intrants.



0
votes

Vous devez également couvrir des cas tels que: le fichier est utilisé par un autre programme, le fichier a été supprimé (copie n'a pas réussi) etc.

Utilisez une manipulation exceptionnelle étendue pour couvrir tous les cas importants pouvant survenir.


0 commentaires

2
votes

Pas sûr de "la bonne façon", mais vous pouvez utiliser l'outil de surveillance ( FileSystemwatcher Je suppose) pour remplir une file d'attente interne que vous utilisez pour le traitement différé. Ou mieux encore: il suffit d'utiliser une file d'attente pour placer des fichiers à l'écart ouvert, vous pouvez donc les réessayer plus tard.


0 commentaires

1
votes

Si vous utilisez FileSystemwatcher i Don Il faut penser qu'il y a une solution robuste à ce problème. Une approche serait essayer / attraper / réessayer plus tard.


0 commentaires

0
votes

Cela dépend, une boucle de réessation est probablement la meilleure que vous puissiez faire, si vous n'avez aucun contrôle sur le processus de copie.

Si vous avez le contrôle:

  • Si le dossier est local, vous pouvez avoir besoin que les personnes qui écrivent des choses à verrouiller le fichier pour un accès exclusif et libérez uniquement la serrure lorsqu'elles sont terminées (ce que je pense est par défaut pour fichier.copy). Sur le côté .NET, vous pourriez avoir une simple boucle de nouvelle tentative, avec une période fraîche.
    • Vous pouvez également écrire le fichier dans un dossier Temp et seulement après écrit le déplacer sur le dir cible. Cela réduit la fenêtre où de mauvaises choses peuvent arriver (mais ne l'élimine pas)
    • Si le dossier est une action SMB, il y a une chance Lockfile ne fonctionne même pas (certaines implémentations Linux). Dans ce cas, l'approche commune consiste à avoir une sorte de fichier de verrouillage, qui est supprimé une fois la personne qui crée le fichier est effectuée. Le problème avec une approche de fichier de verrouillage est que si vous oubliez de le supprimer, vous pouvez avoir des problèmes.
    • À la suite de ces complications, je recommanderais que la réception des données via un service WCF ou un service Web peut être avantageuse car vous avez beaucoup mieux contrôlé.

0 commentaires

11
votes

Je pense que le seul moyen sûr de le faire est d'ouvrir le fichier exclusivement et d'attraper une exception spécifique. Je déteste généralement en utilisant des exceptions pour la logique d'application normale, mais j'ai peur de ce scénario, il n'y a pas d'autre moyen (au moins je ne l'ai pas trouvé encore):

public bool FileIsDone(string path)
{
  try
  {
    using (File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None))
    {
    }
  }
  catch(UnauthorizedAccessException)
  {
    return false;
  }

  return true;
}


0 commentaires

0
votes

En fait, pour éviter les conditions de race, la seule solution sûre consiste à réessayer.

Si vous faites quelque chose comme: xxx

Vous risquez un autre processus de saut entre le moment de la garde et de la déclaration de fichier de processus. Quelle que soit la mise en œuvre de votre "attente de la disponibilité des fichiers", à moins que vous ne puissiez garantir que la post-déverrouillage, vous êtes le premier processus pour y accéder, vous pourriez pas être ce premier utilisateur.

Ceci est plus probable que cela pourrait sembler à première vue, en particulier si plusieurs personnes regardent le fichier, et en particulier s'ils utilisent quelque chose comme l'observateur du système de fichiers. Cours, il n'est toujours pas particulièrement probable même alors ...


0 commentaires

0
votes

Les fichiers sont-ils gros?

Peut-être que vous pourriez essayer de calculer un checksum MD5 sur le fichier?

Si vous mettez le hachage MD5 dans le nom de fichier, vous pouvez la récupérer et essayer de recalculer la somme de contrôle sur le fichier. Lorsque le MD5 est une correspondance, vous pouvez supposer que le fichier est terminé. xxx


0 commentaires

0
votes

Voici une boucle VB.NET que j'utilise. Il attend 2 secondes entre chaque chèque.

 Dim donotcopy As Boolean = True
 While donotcopy = True
     Dim myFile As New FileInfo("Filetocopy")
     Dim sizeInBytes As Long = myFile.Length
     Thread.Sleep(2000)
     Dim myFile2 As New FileInfo("Filetocopy")
     Dim sizeInBytes2 As Long = myFile2.Length
     If sizeInBytes2 = sizeInBytes Then donotcopy = False
 End While


0 commentaires