48 votes

Comment ouvrir un fichier déjà ouvert avec un .net StreamReader?

J'ai quelques .les fichiers csv que j'ai choisi dans le cadre d'un banc de test. Je peux les ouvrir et de les lire sans aucun problème , sauf que j'ai déjà le fichier est ouvert dans Excel, dans lequel cas, je reçois un IOException:

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

153voto

Cheeso Points 87022

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

Le partage de fichiers param est souvent mal compris. Il indique que d'autres dispositifs d'ouverture de fichier peut le faire. Il s'applique à passé comme de l'avenir d'ouverture. Pensez à FileShare pas comme un rétroactive interdiction avant automatiques (par exemple Excel), mais une contrainte qui ne doit pas être violé avec l'ouverture actuelle ou à l'avenir s'Ouvre.

Dans le cas de l'actuel tentez d'ouvrir un fichier, partage de fichiers.Lire "ouvrir ce fichier pour moi avec succès que si elle préavis, ouvre-ouvert seulement pour Lire." Si vous spécifiez FileShare.Lire sur un fichier ouvert en écriture par Excel, votre ouvrir échouera, car ce serait une violation de la contrainte, parce qu'Excel a ouvert pour l'écriture.

Parce que Excel a ouvert le fichier pour l'écriture, vous devez ouvrir le fichier avec FileShare.ReadWrite si vous voulez que votre ouvert à réussir. Une autre façon de penser le partage de fichiers param: il précise "de l'autre gars d'accès au fichier".

Supposons maintenant qu'un autre scénario, dans lequel vous êtes à l'ouverture d'un fichier qui n'est pas actuellement ouvert par une autre application. FileShare.Lu dit "l'avenir ouvre-pouvez ouvrir le fichier avec un accès en Lecture".

Logiquement, ces sémantique du 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 l'autre gars est écrit, et vous n'avez pas de problème à laisser un autre ouvreur écrire le fichier pendant que vous le lisez.

En aucun cas, ne présente de permettre à plusieurs écrivains. Partage de fichiers est similaire à une base de données IsolationLevel. Votre réglage souhaité ici dépend de la "cohérence" des garanties 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.Partage de fichiers est un peu mince. Si vous voulez obtenir le droit de faits, aller à la documentation de la fonction Win32 CreateFile, ce qui explique le concept de partage de fichiers de mieux.

14voto

JaredPar Points 333733

MODIFIER

Je ne suis pas encore 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 l'ai trouver plus tard je vais mettre à jour ce avec l'information.

La meilleure documentation semble être dans le CreateFile fonction. C'est la fonction .Net appel sous le capot afin d'ouvrir un fichier (créer le fichier est un peu un abus de langage). Il a une meilleure documentation de la façon dont le partage de l'aspect de l'ouverture d'un fichier fonctionne. Une autre option est de simplement lire Cheeso réponse

5voto

sipwiz Points 15291

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

0voto

Despertar Points 5365

Un autre problème est que si vous ouvrez un FileStream avec FileShare.ReadWrite , les ouvertures ultérieures de ce fichier doivent également spécifier FileShare.ReadWrite , ou vous obtiendrez le message 'Un autre processus utilise ce fichier 'erreur.

-7voto

DazManCat Points 667

Utilisation du System.Diagnostics;

Vous pouvez simplement appeler Process.Start ("nom de fichier et chemin")

Pas sûr que cela aide mais, c'est ce que je viens d'utiliser pour implémenter un bouton Aperçu PDF sur notre intranet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X