Domanda

Ho alcuni file .csv che sto usando come parte di un banco di prova. Posso aprire e leggere senza problemi meno ho già aperto il file in Excel, nel qual caso mi appare un IOException:

  

System.IO.IOException: Il processo non può accedere al file 'TestData.csv' perché è utilizzato da un altro processo

.

Questo è un frammento dal banco di prova:

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

Si tratta di una limitazione di StreamReader? Posso aprire il file in altre applicazioni (Notepad ++, ad esempio) e quindi non può essere un / S problema O. Forse ho bisogno di usare qualche altra classe? Se qualcuno sa come posso ovviare a questo (a parte la chiusura di Excel!) Sarei molto grato.

È stato utile?

Soluzione

Come dice Jared, non si può fare questo a meno che l'altro soggetto che ha il file aperto permette condiviso legge. Excel consente condiviso legge, anche per i file che ha aperto per la scrittura. Pertanto, è necessario aprire la filestream con il FileShare.ReadWrite parametro.

Il param FileShare è spesso frainteso. Indica che cosa altro apri del file può fare. Essa si applica a passato così come apri futuri. Pensate a FileShare non come un divieto retroattivo apri precedenti (per esempio Excel), ma un vincolo che non deve essere violato con la corrente aperto o un futuro apre.

Nel caso del tentativo corrente di aprire un file, FileShare.Read dice "aprire questo file per me con successo solo se tutte le apri precedenti hanno aperto lo solo per leggere". Se si specifica FileShare.Read su un file che è aperto per la scrittura da Excel, tuo open fallirà, in quanto violerebbe il vincolo, perché Excel ha aperto per la scrittura .

Poiché Excel ha il file aperto per la scrittura, è necessario aprire il file con FileShare.ReadWrite se si desidera tuo aperto per avere successo. Un altro modo di pensare al param FileShare: specifica "l'accesso ai file di l'altro ragazzo".

Ora supponiamo uno scenario diverso, in cui si sta aprendo un file che non è attualmente aperto da qualsiasi altra applicazione. FileShare.Read dice "apri future possano aprire il file solo con l'accesso in lettura".

A rigor di logica, questa semantica hanno senso - FileShare.Read significa, non si vuole leggere il file se l'altro ragazzo sta già scrivendo, e non si vuole l'altro ragazzo per scrivere il file se sei già leggerlo. FileShare.ReadWrite significa, si è disposti a leggere il file anche se l'altro ragazzo sta scrivendo, e si hanno alcun problema lasciando un'altra apertura scrivere il file mentre si sta leggendo.

In nessun caso questo permesso più scrittori. FileShare è simile a un IsolationLevel database. L'impostazione desiderata qui dipende dalla "consistenza" garantisce che desiderate.

Esempio:

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

o

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

Addendum:

Il su System.IO.FileShare è un po 'sottile. Se si desidera ottenere i fatti dritto, vai alla la documentazione la funzione Win32 CreateFile, il che spiega il concetto FileShare meglio.

Altri suggerimenti

Modifica

Sono ancora sicuro al 100% perché questa è la risposta, ma si può risolvere questo problema passando FileShare.ReadWrite al costruttore FileStream.

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

La mia curiosità ha una presa di me in questo momento e sto cercando di capire perché questa è la risposta particolare. Se ho dato fuori dopo mi aggiornerò questo con l'informazione.

La documentazione migliore in realtà sembra essere in href="http://msdn.microsoft.com/en-us/library/aa363858.aspx" rel="noreferrer"> CreateFile funzione . Questa è la funzione Net chiamerà sotto il cofano, al fine di aprire un file (creare il file è un po 'un termine improprio). Ha una migliore documentazione per quanto l'aspetto di condivisione di aprire un file di Works. Un'altra opzione è quella di leggere solo la risposta di Cheeso

Se un altro processo ha un file aperto, spesso è possibile utilizzare File.Copy e quindi aprire la copia. Non è una soluzione elegante ma un pragmatico.

Un altro problema è che se si apre un FileStream con FileShare.ReadWrite, successivamente si apre di quel file inoltre necessario specificare FileShare.ReadWrite, o si otterrà il 'Un altro processo sta utilizzando il file' errore.

Utilizzando le System.Diagnostics;

Si può semplicemente chiamare Process.Start ( “nomefile & Path”)

Non sono sicuro se questo aiuta, ma, questo è quello che ho appena usato per implementare un pulsante Anteprima PDF sul nostro intranet.

scroll top