Come posso aprire un file già aperto con uno .net StreamReader?

Ho alcuni file .csv che sto usando come parte di un banco di prova. Posso aprirli e leggerli senza problemi a meno che non abbia già aperto il file in Excel, nel qual caso ottengo una IOException :

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

Questo è uno snippet 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 ++ per esempio) quindi non può essere un problema di O / S. Forse ho bisogno di usare qualche altra class? Se qualcuno sa come posso aggirare questo (oltre a chiudere Excel!) Sarei molto grato.

Come dice Jared, non è ansible farlo a meno che l’altra entity framework che ha il file aperto consenta letture condivise. Excel consente letture condivise, anche per i file aperti per la scrittura. Pertanto, è necessario aprire il filestream con il parametro FileShare.ReadWrite .

Il parametro FileShare è spesso frainteso. Indica ciò che altri apri del file possono fare. Si applica agli apritori passati e futuri. Pensa a FileShare non come un divieto retroattivo sugli apritori precedenti (ad es. Excel), ma un vincolo che non deve essere violato con l’Open corrente o con qualsiasi Open futuro.

Nel caso del tentativo corrente di aprire un file, FileShare.Read dice “apri questo file per me correttamente solo se è stato aperto da eventuali apri precedenti solo per Read”. Se si specifica FileShare.Read su un file che è aperto per la scrittura da Excel, l’ apertura avrà esito negativo, in quanto violerebbe il vincolo, perché Excel lo ha aperto per la scrittura .

Perché Excel ha il file aperto per la scrittura, è necessario aprire il file con FileShare.ReadWrite se si desidera che l’ apertura abbia esito positivo. Un altro modo di pensare al parametro FileShare: specifica “l’accesso ai file dell’altro ragazzo”.

Supponiamo ora uno scenario diverso, in cui stai aprendo un file che non è attualmente aperto da un’altra app. FileShare.Read dice “gli apritori futuri possono aprire il file solo con l’accesso in lettura”.

Logicamente, questa semantica ha senso – FileShare.Read significa, non si vuole leggere il file se l’altro ragazzo lo sta già scrivendo, e non si vuole che l’altro tocchi il file se lo stai già leggendo. FileShare.ReadWrite significa che sei disposto a leggere il file anche se l’altro ragazzo lo sta scrivendo, e non hai problemi a lasciare che un altro apri scriva il file mentre lo stai leggendo.

In nessun caso questo consente più scrittori. FileShare è simile a un database IsolationLevel. L’impostazione desiderata qui dipende dalle garanzie di “coerenza” richieste.

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:

La documentazione su System.IO.FileShare è un po ‘snella. Se si desidera ottenere i fatti concreti, consultare la documentazione della funzione CreateFile di Win32 , che illustra meglio il concetto di FileShare.

MODIFICARE

Non sono ancora sicuro al 100% perché questa sia la risposta, ma è ansible 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 su di me al momento e sto cercando di capire perché questa è la risposta particolare. Se lo scoprirò più tardi aggiornerò questo con le informazioni.

La migliore documentazione effettivamente sembra essere nella funzione CreateFile . Questa è la funzione. Net chiamerà sotto il cofano per aprire un file (creare file è un po ‘improprio). Ha una documentazione migliore su come funziona l’aspetto della condivisione dell’apertura di un file. Un’altra opzione è quella di leggere la risposta di Cheeso

Se un altro processo ha un file aperto, puoi spesso usare File.Copy e quindi aprire la copia. Non una soluzione elegante ma pragmatica.

Un altro problema è che se apri un FileStream con FileShare.ReadWrite , le successive aperture di quel file FileShare.ReadWrite ANCHE specificare FileShare.ReadWrite , o otterrai l’errore ‘Un altro processo sta usando questo file’.

Utilizzando il System.Diagnostics;

Puoi semplicemente chiamare Process.Start (“nomefile e percorso”)

Non sono sicuro che questo aiuti ma, questo è quello che ho appena usato per implementare un pulsante Anteprima PDF sulla nostra intranet.