J'ai un serveur Web qui lira de gros fichiers binaires (plusieurs mégaoctets) dans des tableaux d'octets. Le serveur pourrait lire plusieurs fichiers en même temps (différentes demandes de page), donc je cherche la façon la plus optimisée de le faire sans trop taxer le CPU. Le code ci-dessous est-il assez bon?
public byte[] FileToByteArray(string fileName)
{
byte[] buff = null;
FileStream fs = new FileStream(fileName,
FileMode.Open,
FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
long numBytes = new FileInfo(fileName).Length;
buff = br.ReadBytes((int) numBytes);
return buff;
}
c#
.net
bytearray
binary-data
Tony_Henrich
la source
la source
byte[] buff = File.ReadAllBytes(fileName)
.Réponses:
Remplacez simplement le tout par:
Cependant, si vous êtes préoccupé par la consommation de mémoire, vous ne devez pas lire le fichier en entier en une seule fois. Vous devriez le faire en morceaux.
la source
Je pourrais faire valoir que la réponse ici est généralement «ne pas». À moins que vous n'ayez absolument besoin de toutes les données à la fois, envisagez d'utiliser une
Stream
API basée sur (ou une variante de lecteur / itérateur). Cela est particulièrement important lorsque vous avez plusieurs opérations parallèles (comme suggéré par la question) pour minimiser la charge système et maximiser le débit.Par exemple, si vous diffusez des données à un appelant:
la source
byte[]
pour une raison quelconque, je suggère d'éviter d'utiliser des flux ou autre chose et d'utiliser simplement l'API fournie par le système.File.ReadAllBytes
.Je pense que ceci:
la source
Votre code peut y être pris en compte (au lieu de File.ReadAllBytes):
Notez la limitation de taille de fichier Integer.MaxValue placée par la méthode Read. En d'autres termes, vous ne pouvez lire qu'un morceau de 2 Go à la fois.
Notez également que le dernier argument du FileStream est une taille de tampon.
Je suggère également de lire sur FileStream et BufferedStream .
Comme toujours, un exemple de programme simple à profiler qui est le plus rapide sera le plus avantageux.
Votre matériel sous-jacent aura également un effet important sur les performances. Utilisez-vous des disques durs sur serveur avec de grands caches et une carte RAID avec cache de mémoire intégré? Ou utilisez-vous un lecteur standard connecté au port IDE?
la source
var binaryReader = new BinaryReader(fs); fileData = binaryReader.ReadBytes((int)fs.Length);
dans cetteusing
déclaration. Mais c'est effectivement ce que l'OP a fait, j'ai juste coupé une ligne de code en le convertissant enfs.Length
auint
lieu d'obtenir lalong
valeur de laFileInfo
longueur et de la convertir.Selon la fréquence des opérations, la taille des fichiers et le nombre de fichiers que vous consultez, il existe d'autres problèmes de performances à prendre en considération. Une chose à retenir est que chacun de vos tableaux d'octets sera libéré à la merci du ramasse-miettes. Si vous ne mettez en cache aucune de ces données, vous pourriez finir par créer beaucoup de déchets et perdre la plupart de vos performances à % Time dans GC. Si les morceaux sont supérieurs à 85 Ko, vous les allouerez au grand tas d'objets (LOH), ce qui nécessitera une collection de toutes les générations à libérer (cela est très coûteux, et sur un serveur arrêtera toute exécution pendant qu'il se déroule) ). De plus, si vous avez une tonne d'objets sur la LOH, vous pouvez vous retrouver avec une fragmentation de la LOH (la LOH n'est jamais compactée), ce qui entraîne de mauvaises performances et des exceptions de mémoire insuffisante. Vous pouvez recycler le processus une fois que vous avez atteint un certain point, mais je ne sais pas si c'est une meilleure pratique.
Le fait est que vous devez considérer le cycle de vie complet de votre application avant de lire simplement tous les octets en mémoire de la manière la plus rapide possible, ou vous pourriez échanger des performances à court terme pour des performances globales.
la source
garbage collector
,chunks
, les performances, les compteurs d'événements , ...Je dirais que
BinaryReader
c'est bien, mais peut être refactorisé à cela, au lieu de toutes ces lignes de code pour obtenir la longueur du tampon:Devrait être mieux que d'utiliser
.ReadAllBytes()
, car j'ai vu dans les commentaires sur la réponse supérieure qui inclut.ReadAllBytes()
que l'un des commentateurs avait des problèmes avec des fichiers> 600 Mo, car unBinaryReader
est destiné à ce genre de chose. En outre, le mettre dans uneusing
déclaration garantit que leFileStream
etBinaryReader
sont fermés et éliminés.la source
new
n'était pas nécessaire là-bas. Supprimé.Dans le cas où «un gros fichier» signifie au-delà de la limite de 4 Go, ma logique de code écrite suivante est appropriée. Le problème clé à noter est le type de données LONG utilisé avec la méthode SEEK. Comme un LONG est capable de pointer au-delà de 2 ^ 32 limites de données. Dans cet exemple, le code traite d'abord le traitement du gros fichier en morceaux de 1 Go, après le traitement des gros morceaux entiers de 1 Go, les octets restants (<1 Go) sont traités. J'utilise ce code pour calculer le CRC des fichiers au-delà de la taille de 4 Go. (en utilisant https://crc32c.machinezoo.com/ pour le calcul de crc32c dans cet exemple)
la source
Utilisez la classe BufferedStream en C # pour améliorer les performances. Un tampon est un bloc d'octets en mémoire utilisé pour mettre en cache des données, réduisant ainsi le nombre d'appels au système d'exploitation. Les tampons améliorent les performances de lecture et d'écriture.
Consultez l'exemple suivant pour un exemple de code et des explications supplémentaires: http://msdn.microsoft.com/en-us/library/system.io.bufferedstream.aspx
la source
BufferedStream
lorsque vous lisez le tout à la fois?utilisez ceci:
la source
Présentation: si votre image est ajoutée en tant que ressource action = incorporée, utilisez GetExecutingAssembly pour récupérer la ressource jpg dans un flux, puis lisez les données binaires du flux dans un tableau d'octets
la source
Je recommanderais d'essayer la
Response.TransferFile()
méthode puis unResponse.Flush()
etResponse.End()
pour servir vos gros fichiers.la source
Si vous traitez des fichiers de plus de 2 Go, vous constaterez que les méthodes ci-dessus échouent.
Il est beaucoup plus facile de transférer le flux vers MD5 et de permettre à celui-ci de segmenter votre fichier pour vous:
la source