Quelle est la meilleure façon de créer un fichier à largeur fixe en C#. J'ai un tas de champs avec des longueurs à écrire. Disons 20, 80, 10, 2, etc., tous alignés à gauche. Existe-t-il un moyen simple de le faire ?
Réponses
Trop de publicités?C'est un système que j'ai fait pour un module configurable d'écriture de fichiers à largeur fixe. Il est configuré avec un fichier XML, la partie pertinente ressemblant à ceci :
<WriteFixedWidth Table="orders" StartAt="1" Output="Return">
<Position Start="1" Length="17" Name="Unique Identifier"/>
<Position Start="18" Length="3" Name="Error Flag"/>
<Position Start="21" Length="16" Name="Account Number" Justification="right"/>
<Position Start="37" Length="8" Name="Member Number"/>
<Position Start="45" Length="4" Name="Product"/>
<Position Start="49" Length="3" Name="Paytype"/>
<Position Start="52" Length="9" Name="Transit Routing Number"/>
</WriteFixedWidth>
StartAt indique au programme si vos positions sont basées sur 0 ou sur 1. Je l'ai rendu configurable parce que j'allais copier des décalages à partir de spécifications et que je voulais que la configuration ressemble le plus possible à la spécification, quel que soit l'indice de départ choisi par l'auteur.
L'attribut Name des balises Position fait référence aux noms des colonnes d'une DataTable.
Le code suivant a été écrit pour .Net 3.5, en utilisant LINQ-to-XML, et la méthode suppose donc qu'on lui transmet un XElement avec la configuration ci-dessus, que vous pouvez obtenir après avoir utilisé XDocument.Load(filename)
pour charger le fichier XML, puis appeler .Descendants("WriteFixedWidth")
sur le XDocument
pour obtenir l'élément de configuration.
public void WriteFixedWidth(System.Xml.Linq.XElement CommandNode, DataTable Table, Stream outputStream)
{
StreamWriter Output = new StreamWriter(outputStream);
int StartAt = CommandNode.Attribute("StartAt") != null ? int.Parse(CommandNode.Attribute("StartAt").Value) : 0;
var positions = from c in CommandNode.Descendants(Namespaces.Integration + "Position")
orderby int.Parse(c.Attribute("Start").Value) ascending
select new
{
Name = c.Attribute("Name").Value,
Start = int.Parse(c.Attribute("Start").Value) - StartAt,
Length = int.Parse(c.Attribute("Length").Value),
Justification = c.Attribute("Justification") != null ? c.Attribute("Justification").Value.ToLower() : "left"
};
int lineLength = positions.Last().Start + positions.Last().Length;
foreach (DataRow row in Table.Rows)
{
StringBuilder line = new StringBuilder(lineLength);
foreach (var p in positions)
line.Insert(p.Start,
p.Justification == "left" ? (row.Field<string>(p.Name) ?? "").PadRight(p.Length,' ')
: (row.Field<string>(p.Name) ?? "").PadLeft(p.Length,' ')
);
Output.WriteLine(line.ToString());
}
Output.Flush();
}
Le moteur est StringBuilder, ce qui est plus rapide que de concaténer des chaînes immuables ensemble, surtout si vous traitez des fichiers de plusieurs mégaoctets.
Essayez FileHelpers : www.filehelpers.com
Voici un exemple : http://www.filehelpers.com/quick_start_fixed.html
Vous pouvez utiliser http://www.filehelpers.com/