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

j'en ai .fichiers csv que j'utilise comme partie d'un banc d'essai. Je peux les ouvrir et les lire sans aucun problème à moins que j'ai déjà le fichier ouvert dans Excel dans lequel cas je reçois un IOException :

Système

.IO.IOException: le processus ne peut pas accéder aux données de test du fichier.csv", car il est utilisé par un autre processus.

voici un extrait du banc d'essai:

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 ça ne peut pas être un problème O/s. Peut-être que j'ai besoin d'utiliser une autre classe? Si quelqu'un sait comment je peux obtenir ce (mis à part la fermeture excel!) Je lui en serais très reconnaissant.

41
demandé sur Jon Cage 2009-05-22 17:19:33

5 réponses

comme dit Jared, vous ne pouvez pas faire cela à moins que l'autre entité qui a le fichier ouvert ne permette des lectures partagées. Excel permet de partagé lit, même pour les fichiers qu'il a ouvert pour l'écriture. Par conséquent, vous devez ouvrir la filestream avec le FileShare .ReadWrite paramètre.

le param FileShare est souvent mal compris. Il indique ce que autres ouvreurs du fichier peuvent faire. Il s'applique aux ouvreurs passés aussi bien que futurs. Pensez à FileShare non pas comme une interdiction rétroactive sur les ouvreurs précédents (par exemple Excel), mais comme une contrainte qui ne doit pas être violée avec L'Open actuel ou tout Open futur.

dans le cas de la tentative actuelle d'ouvrir un fichier, FileShare.Read dit "ouvrir ce fichier pour moi avec succès seulement si elle tous les ouvreurs antérieurs l'ont ouvert seulement pour lire."Si vous spécifiez FileShare.Lire sur un fichier ouvert en écriture par Excel, votre ouvrir échouera, car il violerait la contrainte, parce que Excel l'a ouvert pour écrire .

parce que Excel a le fichier ouvert pour écriture, vous devez ouvrir le fichier avec FileShare.ReadWrite si vous voulez votre ouvert pour réussir. Une autre façon de penser au param FileShare: il spécifie "l'accès au fichier de l'autre type".

supposons maintenant un scénario différent, dans lequel vous ouvrez un fichier qui n'est pas actuellement ouvert par une autre application. FileShare.Read dit que "les futurs ouvreurs ne peuvent ouvrir le fichier qu'avec un accès en lecture".

logiquement, ces sémantiques ont un sens - FileShare.Lire signifie, que vous ne voulez pas lire le fichier si l'autre gars est déjà écrit, et vous ne voulez pas que les autres gars pour écrire le fichier si vous êtes déjà à le lire. FileShare.ReadWrite signifie que vous êtes prêt à lire le fichier même si un autre type l'écrit, et vous n'avez aucun problème à laisser un autre ouvreur écrire le fichier pendant que vous le lisez.

en aucun cas cela ne permet plusieurs écrivains. FileShare est similaire à un niveau D'Isolationd'une base de données. Le réglage que vous souhaitez ici 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))
{
}

Addendum:

la documentation sur le système.IO.FileShare est un peu mince. Si vous voulez obtenir les faits exacts, allez à la documentation pour la fonction Win32 CreateFile , qui explique le concept FileShare mieux.

145
répondu Cheeso 2014-07-02 01:56:19

MODIFIER

Je ne suis toujours pas sûr à 100% pourquoi c'est la réponse, mais vous pouvez résoudre ce problème en passant FileShare.ReadWrite pour le constructeur FileStream.

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

Ma curiosité a une prise de moi à l'instant et j'essaie de comprendre pourquoi c'est la réponse particulière. Si je le découvre plus tard, je le mettrai à jour avec les informations.

la meilleure documentation apparaît réellement pour être dans la fonction CreateFile . C'est la fonction.Net appellera sous le capot afin d'ouvrir un fichier (create file est un peu un nom erroné). Il a une meilleure documentation pour la façon dont l'aspect de partage de l'ouverture d'un fichier fonctionne. Une autre option est de simplement lire la réponse de Cheeso

14
répondu JaredPar 2009-05-22 14:27:22

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

5
répondu sipwiz 2009-05-22 13:25:04

un autre hic est que si vous ouvrez un FileStream avec FileShare.ReadWrite , les ouvertures subséquentes de ce fichier doivent également spécifier FileShare.ReadWrite , ou vous obtiendrez l'erreur "Un autre processus utilise ce fichier".

0
répondu Despertar 2012-10-06 06:29:48

utilisant le système.Diagnostics;

vous pouvez simplement appeler Processus.Début("nom de fichier et Chemin d'accès")

Je ne suis pas sûr que cela aide, mais c'est ce que je viens d'utiliser pour implémenter un bouton PDF Preview sur notre intranet.

-7
répondu DazManCat 2012-11-29 13:16:30