Comment puis-je ouvrir un fichier déjà ouvert avec un .R StreamReader?

J’ai quelques fichiers .csv que j’utilise dans le cadre d’un banc de test. Je peux les ouvrir et les lire sans aucun problème à moins que le fichier ne soit déjà ouvert dans Excel, auquel cas je reçois une IOException :

System.IO.IOException: le processus ne peut pas accéder au fichier ‘TestData.csv’ car il est utilisé par un autre processus.

Ceci est un extrait du banc de test:

 using (CsvReader csv = new CsvReader(new StreamReader(new FileStream(fullFilePath, FileMode.Open, FileAccess.Read)), false)) { // Process the file } 

Est-ce une limitation de StreamReader? Je peux ouvrir le fichier dans d’autres applications (Notepad ++ par exemple), donc ce ne peut pas être un problème d’O / S. Peut-être que je dois utiliser une autre classe? Si quelqu’un sait comment je peux contourner cela (en plus de fermer Excel!), Je lui en serais très reconnaissant.

Comme Jared dit, vous ne pouvez pas faire cela à moins que l’autre entité qui a le fichier ouvert autorise les lectures partagées. Excel autorise les lectures partagées, même pour les fichiers ouverts en écriture. Par conséquent, vous devez ouvrir le fichier filestream avec le paramètre FileShare.ReadWrite .

Le paramètre FileShare est souvent mal compris. Il indique ce que les autres ouvreurs du fichier peuvent faire. Cela s’applique aussi bien aux ouvreurs passés qu’aux futurs. Pensez à FileShare non pas comme une interdiction rétroactive des ouvertures antérieures (par exemple Excel), mais comme une contrainte qui ne doit pas être violée avec l’Open en cours ou les futurs Open.

Dans le cas de la tentative actuelle d’ouvrir un fichier, FileShare.Read dit “ouvrez ce fichier avec succès uniquement si des ouvreurs précédents l’ont ouvert uniquement pour Read”. Si vous spécifiez FileShare.Read sur un fichier ouvert pour l’écriture par Excel, votre ouverture échouera, car elle violerait la contrainte, car Excel l’a ouvert pour l’écriture .

Excel ayant le fichier ouvert pour l’écriture, vous devez ouvrir le fichier avec FileShare.ReadWrite si vous souhaitez que votre open réussisse. Une autre façon de penser au paramètre FileShare: il spécifie “l’access à l’autre fichier”.

Supposons maintenant un scénario différent, dans lequel vous ouvrez un fichier qui n’est actuellement ouvert par aucune autre application. FileShare.Read indique que “les futurs ouvreurs ne peuvent ouvrir le fichier qu’avec un access en lecture”.

Logiquement, ces sémantiques ont du sens – FileShare.Read signifie que vous ne voulez pas lire le fichier si l’autre est déjà en train de l’écrire et que vous ne voulez pas que l’autre mette le fichier si vous le lisez déjà. FileShare.ReadWrite signifie que vous êtes prêt à lire le fichier même si l’autre le écrit, et que vous n’avez aucun problème à laisser un autre utilisateur écrire le fichier pendant que vous le lisez.

Cela ne permet en aucun cas à plusieurs auteurs. FileShare est similaire à une firebase database IsolationLevel. Votre réglage souhaité dépend des garanties de “cohérence” dont vous avez besoin.

Exemple:

 using (Stream s = new FileStream(fullFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { ... } 

ou,

 using (Stream s = System.IO.File.Open(fullFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { } 

Addenda:

La documentation sur System.IO.FileShare est un peu mince. Si vous souhaitez obtenir les faits, consultez la documentation de la fonction Win32 CreateFile , qui explique mieux le concept FileShare.

MODIFIER

Je ne suis toujours pas sûr à 100% de la raison de cette réponse, mais vous pouvez résoudre ce problème en transmettant FileShare.ReadWrite au constructeur FileStream.

 using (CsvReader csv = new CsvReader(new StreamReader(new FileStream(fullFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)), false) { ... } 

Ma curiosité me tient en ce moment et j’essaie de comprendre pourquoi c’est la réponse. Si je le découvre plus tard, je le mettrai à jour avec les informations.

La meilleure documentation semble être la fonction CreateFile . C’est la fonction que .Net appelle sous le capot pour ouvrir un fichier (créer un fichier est un peu trompeur). Il dispose d’une meilleure documentation sur le fonctionnement de l’aspect de partage d’un fichier. Une autre option consiste à lire la réponse de Cheeso

Si un autre processus a un fichier ouvert, vous pouvez souvent utiliser File.Copy, puis ouvrir la copie. Pas une solution élégante mais pragmatique.

Un autre problème est que si vous ouvrez un FileStream avec FileShare.ReadWrite , les prochaines ouvertures de ce fichier doivent également spécifier FileShare.ReadWrite , ou vous obtiendrez l’erreur “Un autre processus utilise ce fichier”.

Utilisation du System.Diagnostics;

Vous pouvez simplement appeler Process.Start (“filename & Path”)

Je ne sais pas si cela aide, mais c’est ce que je viens d’utiliser pour implémenter un bouton Aperçu PDF sur notre intranet.