38 votes

Création d'un fichier à largeur fixe en C#

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 ?

52voto

Wheelie Points 2365

Vous pouvez utiliser string.Format pour ajouter facilement des espaces à une valeur. par exemple

string a = String.Format("|{0,5}|{1,5}|{2,5}", 1, 20, 300);
string b = String.Format("|{0,-5}|{1,-5}|{2,-5}", 1, 20, 300);

// 'a' will be equal to "|    1|   20|  300|"
// 'b' will be equal to "|1    |20   |300  |"

27voto

C. Lawrence Wenham Points 11271

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.

9voto

Leandro Oliveira Points 229

Essayez FileHelpers : www.filehelpers.com

Voici un exemple : http://www.filehelpers.com/quick_start_fixed.html

7voto

Andrew Burgess Points 3053

Utilisez la fonction .PadRight (pour les données alignées à gauche) de la classe String. Ainsi :

handle.WriteLine(s20.PadRight(20));
handle.WriteLine(s80.PadRight(80));
handle.WriteLine(s10.PadRight(10));
handle.WriteLine(s2.PadRight(2));

5voto

Yitzchok Points 528

Vous pouvez utiliser http://www.filehelpers.com/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X