Modo affidabile per convertire un file in un byte []


85

Ho trovato il seguente codice sul web:

private byte [] StreamFile(string filename)
{
   FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read);

   // Create a byte array of file stream length
   byte[] ImageData = new byte[fs.Length];

   //Read block of bytes from stream into the byte array
   fs.Read(ImageData,0,System.Convert.ToInt32(fs.Length));

   //Close the File Stream
   fs.Close();
   return ImageData; //return the byte data
}

È abbastanza affidabile da usare per convertire un file in byte [] in c # o c'è un modo migliore per farlo?


3
Dovresti inserire fs.Close()la parte finale di un'istruzione try-latest che racchiude il resto del codice, per assicurarti che Closevenga effettivamente chiamato.
Joren,

Risposte:


221
byte[] bytes = System.IO.File.ReadAllBytes(filename);

Questo dovrebbe fare il trucco. ReadAllBytes apre il file, ne legge il contenuto in un nuovo array di byte, quindi lo chiude. Ecco la pagina MSDN per quel metodo.


Ciò causerebbe un blocco dei file?
JL.

Voglio dire - una volta che il byte [] è popolato, il file non sarà ancora bloccato?
JL.

3
No, non lo sarebbe: il file viene chiuso non appena l'array di byte viene popolato.
Erik Forbes,

4
L'unico problema minore è che se hai un file di grandi dimensioni (diciamo 500 MB o 1 GB, ecc.) Assegnerà quella quantità di memoria per il tuo array di byte. Quindi a volte vale la pena girare intorno a un .Read (..) ed estrarlo lentamente. Ovviamente tutto dipende dalla dimensione del file. :)
Joshua

3
Questo fallirà se il file viene aperto da un altro processo, il metodo OP funzionerà con l'aggiunta di FileShare.ReadWriteafterFile.Read
Motes

28
byte[] bytes = File.ReadAllBytes(filename) 

o ...

var bytes = File.ReadAllBytes(filename) 

13
Sul serio? 'var' è perfettamente accettabile in questo caso - il tipo di ritorno è chiaramente indicato nel nome del metodo ...
Erik Forbes

4
+1 per l'utilizzo originario var. È la mia opinione personale (e quella di molti altri), che dovrebbe essere utilizzato il più possibile. :) La questione è stata discussa più volte su questo sito prima, infatti.
Noldorin

8
Anche +1 per l'utilizzo di var ... @silky, immagino che tutti siano liberi di avere un'opinione sull'opportunità o meno di utilizzare o meno le nuove funzionalità del linguaggio quando vengono introdotte, ma il downvoting di una risposta perché non è conforme alla tua opinione non lo è di cosa pensavo trattasse questo forum. certamente ha poco a che fare con la domanda di JL.
Charles Bretana,

6
Penso che dovresti considerare più delle preferenze personali quando si vota. Questa è una risposta perfettamente valida, con o senza var. Tendo a pensare che qualsiasi programmatore che ha bisogno di precisare manualmente ed esplicitamente i tipi sta lavorando a un livello di astrazione troppo basso. Non dovrebbe importare quale sia il tipo preciso di variabile, solo a cosa serve la variabile . Se memorizza i byte dal file, allora dovrebbe essere quello che conta. Non se si tratta di un elenco, di un array o di un MyCustomContainer.
jalf

8
Se varfosse stato pertinente per la risposta effettiva, discutere sull'uso di esso avrebbe avuto senso. Ma qui, la parte importante della risposta è giusta File.ReadAllBytes(filename). Come e se il risultato viene memorizzato in una variabile è irrilevante quanto la denominazione della variabile o lo spazio dopo il =.
jalf

12

Non ripetere ciò che tutti hanno già detto, ma tieni a portata di mano il seguente cheat sheet per le manipolazioni dei file:

  1. System.IO.File.ReadAllBytes(filename);
  2. File.Exists(filename)
  3. Path.Combine(folderName, resOfThePath);
  4. Path.GetFullPath(path); // converts a relative path to absolute one
  5. Path.GetExtension(path);

6

Tutte queste risposte con .ReadAllBytes(). Un'altra domanda simile (non dico duplicata, poiché stavano cercando di rifattorizzare il loro codice) è stata posta su SO qui: Il modo migliore per leggere un file di grandi dimensioni in un array di byte in C #?

È stato fatto un commento su uno dei post riguardanti .ReadAllBytes():

File.ReadAllBytes throws OutOfMemoryException with big files (tested with 630 MB file 
and it failed) – juanjo.arana Mar 13 '13 at 1:31

Un approccio migliore, per me, sarebbe qualcosa del genere, con BinaryReader:

public static byte[] FileToByteArray(string fileName)
{
    byte[] fileData = null;

    using (FileStream fs = File.OpenRead(fileName)) 
    { 
        var binaryReader = new BinaryReader(fs); 
        fileData = binaryReader.ReadBytes((int)fs.Length); 
    }
    return fileData;
}

Ma sono solo io ...

Ovviamente, tutto questo presuppone che tu abbia la memoria per gestirlo byte[]una volta letto, e non ho inserito il File.Existscontrollo per assicurarti che il file sia lì prima di procedere, come avresti fatto prima di chiamare questo codice.


1
C'è un errore nel codice, non è necessario il nuovo
nell'istruzione

Non tanto un errore (credo che il codice sarebbe comunque compilabile) ma l'ho rimosso lo stesso. Buona pesca.
vapcguy

3

sembra abbastanza buono come versione generica. Puoi modificarlo per soddisfare le tue esigenze, se sono abbastanza specifiche.

verifica anche le eccezioni e le condizioni di errore, come il file non esiste o non può essere letto, ecc.

puoi anche fare quanto segue per risparmiare spazio:

 byte[] bytes = System.IO.File.ReadAllBytes(filename);

2

Altri hanno notato che puoi usare il built-in File.ReadAllBytes. Il metodo integrato va bene, ma vale la pena notare che il codice che pubblichi sopra è fragile per due motivi:

  1. Streamis IDisposable- dovresti inserire l' FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read)inizializzazione in una clausola using per assicurarti che il file sia chiuso. In caso contrario, il flusso rimane aperto se si verifica un errore, il che significa che il file rimane bloccato e ciò può causare altri problemi in seguito.
  2. fs.Readpotrebbe leggere meno byte di quelli richiesti. In generale, il .Readmetodo di Streamun'istanza leggerà almeno un byte, ma non necessariamente tutti i byte richiesti. Dovrai scrivere un ciclo che riprova a leggere finché tutti i byte non vengono letti. Questa pagina lo spiega in modo più dettagliato.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.