J'ai du code et quand il s'exécute, il lance un IOException
, disant que
Le processus ne peut pas accéder au fichier 'filename' car il est utilisé par un autre processus
Qu'est-ce que cela signifie et que puis-je faire?
c#
.net
language-agnostic
ioexception
Adriano Repetti
la source
la source
Réponses:
Quelle est la cause?
Le message d'erreur est assez clair: vous essayez d'accéder à un fichier, et il n'est pas accessible car un autre processus (ou même le même processus) fait quelque chose avec lui (et il n'a permis aucun partage).
Débogage
Cela peut être assez facile à résoudre (ou assez difficile à comprendre), selon votre scénario spécifique. Voyons en voir.
Votre processus est le seul à accéder à ce fichier.
Vous êtes sûr que l' autre processus est votre propre processus. Si vous savez que vous ouvrez ce fichier dans une autre partie de votre programme, vous devez d'abord vérifier que vous fermez correctement le descripteur de fichier après chaque utilisation. Voici un exemple de code avec ce bogue:
Heureusement
FileStream
implémenteIDisposable
, il est donc facile d'encapsuler tout votre code dans uneusing
instruction:Ce modèle garantira également que le fichier ne sera pas laissé ouvert en cas d'exceptions (cela peut être la raison pour laquelle le fichier est utilisé: quelque chose s'est mal passé, et personne ne l'a fermé; voir cet article pour un exemple).
Si tout semble bien (vous êtes sûr de toujours fermer tous les fichiers que vous ouvrez, même en cas d'exceptions) et que vous avez plusieurs threads de travail, alors vous avez deux options: retravailler votre code pour sérialiser l'accès aux fichiers (pas toujours faisable et pas toujours voulu) ou appliquez un modèle de nouvelle tentative . C'est un modèle assez courant pour les opérations d'E / S: vous essayez de faire quelque chose et en cas d'erreur, vous attendez et réessayez (vous êtes-vous demandé pourquoi, par exemple, Windows Shell prend un certain temps pour vous informer qu'un fichier est en cours d'utilisation et ne peut pas être supprimé?). En C #, c'est assez facile à implémenter (voir également de meilleurs exemples sur les E / S disque , le réseau et l' accès aux bases de données ).
Veuillez noter une erreur courante que nous voyons très souvent sur StackOverflow:
Dans ce cas
ReadAllText()
échouera car le fichier est en cours d'utilisation (File.Open()
dans la ligne précédente). Ouvrir le fichier au préalable n'est pas seulement inutile mais également erroné. De même pour toutes lesFile
fonctions qui ne renvoient pas une poignée dans le fichier que vous travaillez avec:File.ReadAllText()
,File.WriteAllText()
,File.ReadAllLines()
,File.WriteAllLines()
et d' autres (comme lesFile.AppendAllXyz()
fonctions) seront tous ouverts et fermez le fichier par eux - mêmes.Votre processus n'est pas le seul à accéder à ce fichier
Si votre processus n'est pas le seul à accéder à ce fichier, l'interaction peut être plus difficile. Un modèle de nouvelle tentative aidera (si le fichier ne doit pas être ouvert par quelqu'un d'autre mais qu'il l'est, alors vous avez besoin d'un utilitaire comme Process Explorer pour vérifier qui fait quoi ).
Façons d'éviter
Le cas échéant, utilisez toujours des instructions using pour ouvrir les fichiers. Comme indiqué dans le paragraphe précédent, cela vous aidera activement à éviter de nombreuses erreurs courantes (voir cet article pour un exemple sur la façon de ne pas l'utiliser ).
Si possible, essayez de décider à qui appartient l'accès à un fichier spécifique et centralisez l'accès grâce à quelques méthodes bien connues. Si, par exemple, vous avez un fichier de données dans lequel votre programme lit et écrit, vous devez insérer tout le code d'E / S dans une seule classe. Cela facilitera le débogage (car vous pouvez toujours y mettre un point d'arrêt et voir qui fait quoi) et aussi ce sera un point de synchronisation (si nécessaire) pour un accès multiple.
N'oubliez pas que les opérations d'E / S peuvent toujours échouer, voici un exemple courant:
Si quelqu'un supprime le fichier après
File.Exists()
mais avantFile.Delete()
, il jettera unIOException
dans un endroit où vous pourriez vous sentir mal en sécurité.Chaque fois que c'est possible, appliquez un modèle de nouvelle tentative , et si vous utilisez
FileSystemWatcher
, envisagez de reporter l'action (car vous serez notifié, mais une application peut toujours travailler exclusivement avec ce fichier).Scénarios avancés
Ce n'est pas toujours aussi simple, vous devrez peut-être partager l'accès avec quelqu'un d'autre. Si, par exemple, vous lisez du début et écrivez jusqu'à la fin, vous avez au moins deux options.
1) partager la même chose
FileStream
avec les fonctions de synchronisation appropriées (car il n'est pas thread-safe ). Voir ceci et ces messages pour un exemple.2) utilisez une
FileShare
énumération pour indiquer au système d'exploitation d'autoriser d'autres processus (ou d'autres parties de votre propre processus) à accéder au même fichier simultanément.Dans cet exemple, j'ai montré comment ouvrir un fichier pour l'écriture et le partager pour la lecture; Veuillez noter que lors de la lecture et de l'écriture de chevauchements, il en résulte des données non définies ou invalides. C'est une situation qui doit être gérée lors de la lecture. Notez également que cela ne permet pas d'accéder au
stream
thread-safe, donc cet objet ne peut pas être partagé avec plusieurs threads à moins que l'accès ne soit synchronisé d'une manière ou d'une autre (voir les liens précédents). D'autres options de partage sont disponibles et ouvrent des scénarios plus complexes. Veuillez consulter MSDN pour plus de détails.En général, N processus peuvent lire tous ensemble à partir du même fichier, mais un seul doit écrire.Dans un scénario contrôlé, vous pouvez même activer les écritures simultanées, mais cela ne peut pas être généralisé en quelques paragraphes de texte dans cette réponse.
Est-il possible de déverrouiller un fichier utilisé par un autre processus? Ce n'est pas toujours sûr et pas si facile mais oui, c'est possible .
la source
File.Create(path)
, vous devez ajouter.Close()
la fin de celui-ci avant d'écrire dessus. Il y a des pièges comme ça, en plus desusing
instructions pour écrire les fichiers, puis pour les supprimer après eux. Vous devriez publier le code dans votre question pour savoir comment vous créez et supprimez votre fichier. Mais cela correspond probablement à quelque chose mentionné ci-dessus.Directory.SetCreationTimeUTC()
mais il échoue lorsque l'Explorateur de fichiers est ouvert, affirmant que le répertoire est accédé par un autre processus. Comment dois-je gérer cette situation?L'utilisation de FileShare a résolu mon problème d'ouverture de fichier même s'il est ouvert par un autre processus.
la source
J'ai rencontré un problème lors du téléchargement d'une image, je n'ai pas pu la supprimer et j'ai trouvé une solution. GL hf
la source
J'ai eu cette erreur parce que je faisais File.Move vers un chemin de fichier sans nom de fichier, je dois spécifier le chemin complet dans la destination.
la source
L'erreur indique qu'un autre processus tente d'accéder au fichier. Peut-être que vous ou quelqu'un d'autre l'avez ouvert pendant que vous essayez de lui écrire. "Lire" ou "Copier" ne cause généralement pas cela, mais y écrire ou appeler delete le ferait.
Il y a quelques éléments de base pour éviter cela, comme d'autres réponses l'ont mentionné:
En
FileStream
opération, placez-le dans unusing
bloc avec unFileShare.ReadWrite
mode d'accès.Par exemple:
Notez que ce
FileAccess.ReadWrite
n'est pas possible si vous utilisezFileMode.Append
.J'ai rencontré ce problème lorsque j'utilisais un flux d'entrée pour faire un
File.SaveAs
lorsque le fichier était en cours d'utilisation. Dans mon cas, j'ai trouvé que je n'avais pas du tout besoin de le sauvegarder dans le système de fichiers, donc j'ai fini par le supprimer, mais j'aurais probablement pu essayer de créer un FileStream dans uneusing
instruction avecFileAccess.ReadWrite
, un peu comme le code au dessus.Enregistrer vos données dans un fichier différent et revenir en arrière pour supprimer l'ancien lorsqu'il s'avère qu'il n'est plus utilisé, puis renommer celui qui a été enregistré avec succès au nom de l'original est une option. La façon dont vous testez le fichier en cours d'utilisation est effectuée via le
ligne dans mon code ci-dessous, et pourrait être fait dans un service Windows, en boucle, si vous avez un fichier particulier que vous souhaitez regarder et supprimer régulièrement lorsque vous souhaitez le remplacer. Si vous n'avez pas toujours le même fichier, un fichier texte ou une table de base de données pourrait être mis à jour pour que le service vérifie toujours les noms de fichiers, puis effectue cette vérification des processus et effectue ensuite le processus tue et supprime, comme je le décris dans l'option suivante. Notez que vous aurez besoin d'un nom d'utilisateur et d'un mot de passe de compte disposant des privilèges d'administrateur sur l'ordinateur donné, bien sûr, pour effectuer la suppression et la fin des processus.
Lorsque vous ne savez pas si un fichier sera en cours d'utilisation lorsque vous essayez de l'enregistrer, vous pouvez fermer tous les processus qui pourraient l'utiliser, comme Word, s'il s'agit d'un document Word, avant l'enregistrement.
S'il est local, vous pouvez le faire:
S'il est distant, vous pouvez le faire:
où
txtUserName
est sous la forme deDOMAIN\user
.Disons que vous ne connaissez pas le nom du processus qui verrouille le fichier. Ensuite, vous pouvez faire ceci:
Notez qu'il
file
doit s'agir du chemin UNC:\\computer\share\yourdoc.docx
pour que leProcess
puisse savoir sur quel ordinateur il se trouve etp.MachineName
être valide.Vous trouverez ci-dessous la classe à laquelle ces fonctions utilisent, ce qui nécessite l'ajout d'une référence
System.Management
. Le code a été écrit à l'origine par Eric J .:la source
Comme d'autres réponses de ce fil l'ont souligné, pour résoudre cette erreur, vous devez inspecter attentivement le code pour comprendre où le fichier est verrouillé.
Dans mon cas, j'envoyais le fichier sous forme de pièce jointe à un e-mail avant d'effectuer l'opération de déplacement.
Le fichier a donc été verrouillé pendant quelques secondes jusqu'à ce que le client SMTP ait fini d'envoyer l'e-mail.
La solution que j'ai adoptée était de déplacer d'abord le fichier, puis d'envoyer l'e-mail. Cela a résolu le problème pour moi.
Une autre solution possible, comme indiqué précédemment par Hudson, aurait été de jeter l'objet après utilisation.
la source
File.Move()
ne fonctionnera pas et donne la même erreur. Si vous ajoutez simplement un fichier à un e-mail, je ne pense pas que ce soit une erreur lors de son utilisation pendant l'Attachments.Add()
opération car il ne s'agit que d'une opération de copie. Si c'est le cas pour une raison quelconque, vous pouvez le copier dans un répertoire Temp, joindre la copie et supprimer le fichier copié par la suite. Mais je ne pense pas, si l'OP veut modifier un fichier et l'utiliser, que ce genre de solution (dont vous n'avez pas montré le code, seule la partie jointe) fonctionnerait..Dispose()
est toujours une bonne idée, mais pas pertinente ici à moins que le fichier ne soit ouvert dans une opération antérieure.J'ai eu le scénario suivant qui causait la même erreur:
La plupart des fichiers étaient de petite taille, cependant, quelques-uns étaient volumineux et toute tentative de suppression entraînait une erreur de fichier impossible d'accès .
Ce n’était pas facile à trouver, cependant, la solution était aussi simple que d’ attendre «que la tâche soit terminée»:
la source
Mon code ci-dessous résout ce problème, mais je suggère que vous devez d'abord comprendre ce qui cause ce problème et essayer la solution que vous pouvez trouver en changeant le code
Je peux donner un autre moyen de résoudre ce problème, mais la meilleure solution est de vérifier votre structure de codage et d'essayer d'analyser ce qui fait que cela se produit, si vous ne trouvez aucune solution, vous pouvez utiliser ce code ci-dessous
la source
GC.*()
vous avez probablement d'autres problèmes avec votre code. 2) Le message est localisé et fragile , utilisez plutôt HRESULT. 3) Vous voudrez peut-être dormir avecTask.Delay()
(et dix secondes sont en quelque sorte excessives dans de nombreux cas). 4) Vous n'avez pas de condition de sortie: ce code pourrait se bloquer pour toujours. 5) Vous n'avez certainement pas besoingoto
ici. 6) AttraperException
est généralement une mauvaise idée, dans ce cas aussi parce que ... 6) Si autre chose se produit, vous avalez l'erreur.GC.Collect()
a été celui de traiter certains objets COM.