Combinez plusieurs fichiers en un seul fichier
Code:
static void MultipleFilesToSingleFile(string dirPath, string filePattern, string destFile)
{
string[] fileAry = Directory.GetFiles(dirPath, filePattern);
Console.WriteLine("Total File Count : " + fileAry.Length);
using (TextWriter tw = new StreamWriter(destFile, true))
{
foreach (string filePath in fileAry)
{
using (TextReader tr = new StreamReader(filePath))
{
tw.WriteLine(tr.ReadToEnd());
tr.Close();
tr.Dispose();
}
Console.WriteLine("File Processed : " + filePath);
}
tw.Close();
tw.Dispose();
}
}
J'ai besoin pour optimiser ce qu'elle est extrêmement lente: prend 3 minutes pour 45 fichiers de taille moyenne de 40 — 50 Mo fichier XML.
Veuillez noter: 45 fichiers d'une moyenne de 45 MO est juste un exemple, il peut être n
nombre de fichiers de m
la taille, où n
est en milliers & m
peut-être de la moyenne de 128 Ko. En bref, il peut varier.
Pourriez-vous nous apporter des points de vue sur l'optimisation?
- Avez-vous besoin d'attendre cette méthode fait? Si pas, essayez de async
- 45 fichiers d'une moyenne de 45 MO chacun soit un total d'un peu plus de 2 GO. Combien de temps pensez-vous que prendre? Disk I/O sera prise en compte pour une grande partie du temps, c'est prenant.
- L'appel de
Dispose
est superflu, comme les objets que vous êtes l'élimination sont déjà à l'aide du bloc (qui prendra soin de Disposer pour vous). - Vous êtes en train de charger dans la mémoire de chaque fichier. Ces grandes chaînes d'aller dans le grand tas d'objets, pourquoi ne pas vous lire les petits morceaux de données (réutilisation de la mémoire tampon)? Fermer/Débarrasser sont inutiles en raison de l'utilisation de déclaration. Un raw Flux est assez parce que vous n'avez pas à gérer/modifier n'importe quel encodage. Après avoir fait tout cela...vous verrez, la performance ne sera pas trop changé, sans doute parce que la plupart du temps est passé en I/O. Si le fichier de sortie n'est pas sur le même disque que les entrées alors vous pourriez même essayer de faire de la lecture et de l'écriture asynchrone (pré-lecture du fichier suivant/morceau lors de l'écriture).
- 45 fichiers d'une moyenne de 45 MO est juste un exemple, il peut être 'n' nombres de fichiers de 'm' de taille n, où n est dans milliers & m peut être de avg. 128 ko. En bref, il peut varier.
- Nope, Pas d'attente du tout.J'ai juste besoin de faire l'mentionnées activité en un minimum de temps, c'est de l'optimisation, je suis à la recherche d'
- Vous avez manqué mon point. 🙂 Encore une fois, les e/S disque va être une très grande partie du temps, et la plus grande
n
est plus il va prendre juste pour les i/o disque. En plus de cela, vous avez les frais généraux réels de création d'objet, de l'allocation de mémoire, GC, et ainsi de suite. - oui vrai,de sorte que toute chose comme parallèle de la lecture est possible d'assurer l'ordre d'écriture reste inchangé. Sera-ce plus rapide?
- Merci, Disposer est considéré comme une meilleure pratique, donc j'avais gardé, sera certainement l'enlever maintenant. Merci pour les précisions!
- une dernière remarque: si vous avez+ de 1000 fichiers, vous pouvez envisager d'utiliser un Répertoire.EnumerateFiles au lieu de Répertoire.GetFiles. Pour la même raison, je vous suggère de vérifier la taille du fichier de décider quelle méthode de copie est meilleure (une seule lecture ou plusieurs petits morceaux). Enfin, ne pas utiliser la fonction d'assistance AppendAllText: il s'ouvre et fermer le fichier pour chaque écriture.
- Est-il conseillé d'utiliser quelques conseils & code unsafe pour fixer le processus?
- non, la plupart du temps est consacré à la (lente) I/O disque, vous ne serez pas obtenir quelque chose pour utiliser le code unsafe. Il est préférable de simplement restructurer le code afin de ne pas gaspiller la mémoire/CPU et d'améliorer l'algorithme (ok, même le multithreading pour les e/S est d'une certaine manière empirique). Eh bien, vous pouvez envisager de réécrire votre code pour utiliser ReadFileScatter et WriteFileGather mais franchement je ne sais pas combien de boost de performance, vous aurez (par rapport à l'effort de les utiliser, au moins jusqu'à très grande vitesse des disques Ssd sera assez commun).
- Double Possible de moyen Efficace de combiner plusieurs fichiers de texte
Vous devez vous connecter pour publier un commentaire.
Pourquoi ne pas simplement utiliser le
Stream.CopyTo()
méthode?Une option est d'utiliser le copie de commande, et de le laisser faire ce qui est bien.
Quelque chose comme:
/b
interrupteur pour forcercopy
de les traiter comme des binaire fichiers (puis il va ajouter eux). Si vous avez besoin d'une ligne de commande solution c'est bon (ce n'est pas le mieux solution de point de vue des performances, mais l'effort à faire de ce bien est assez élevé).cmd.exe
je n'avais pas pris. Je vais supprimer mes commentaires, mais heureusement, je n'ai pas downvote. 🙂 Merci pour la correction, je l'ai toujours aimé apprendre des choses, même si je suis en tort dans le processus. (Et +1, pendant que j'y suis.)Je voudrais utiliser un BlockingCollection de lecture vous permet de lire et d'écrire en même temps.
Clairement écrivez à un disque physique distinct pour éviter de matériel de contention.
Ce code permet de préserver l'ordre.
Lire va être plus rapide que d'écrire, donc pas besoin de lire en parallèle.
De nouveau, car lire est va être plus rapide limite la taille de la collection afin de lire n'obtient pas plus loin, d'écrire qu'il en a besoin.
Une tâche simple à lire le seul côté en parallèle, alors que l'écriture de la actuel a le problème des différentes tailles de fichier - écrire un fichier de petite taille est plus rapide que de lire un grand.
- Je utiliser ce modèle à lire et à analyser le texte sur T1 et puis l'insérer à SQL sur T2.
BlockingCollection Classe
Plusieurs choses que vous pouvez faire:
J'ai mon expérience de la mémoire tampon par défaut la taille peut être augmentée avec des prestations jusqu'à environ 120K, je soupçonne que la définition d'un grand tampon sur tous les cours d'eau sera la plus simple et la plus notable de la performance de rappel:
Utiliser le
Stream
de la classe, pas leStreamReader
classe.using
déclaration.