user9969
user9969

Reputation: 16040

Writing to a file and formatting rows .Suggestion needed

Wondering if you some better suggestions that what I have come up with.

I have a requirement to write a text file in a particular format Each field must start at the position stated and must be padded with blank spaces till the next one.

Example:

        Field            Position in the row
        Name             1  
        Surname          20
        Address          50
        Country          90
        DOB              120
        MaritalStatus    160

Below is my prototype attempt, is there a neater better way of doing this? Need to test the position in the row is correct in a unit test?

Any suggestions?

              class Program
                {
                    static void Main(string[] args)
                    {
                        Customer customer=new Customer();
                        customer.Name = "Jo";
                        customer.Surname = "Bloggs";
                        customer.Address = " 1 NewYork Road";
                        customer.Country = "UK";
                        customer.DOB = "29/04/1990";
                        customer.MaritalStatus = "Married";

                        StringBuilder sb=new StringBuilder();
                        CreateHeader(customer,sb);
                        sb.AppendLine("");
                        CreateRow(customer, sb);
                        sb.AppendLine("");

                        IOExtensions.WriteToFile(sb.ToString(), "TestFile.txt");

                    }

                    private static void CreateHeader(Customer customer,StringBuilder sb)
                    {
                        /*
                           * 
                          Field            Position in the row
                          Name             1    
                          Surname          20
                          Address          50
                          Country          90
                          DOB              120
                          MaritalStatus    160

                           */
                        //First Field
                        sb.Append(FormatValue("Name", 19));
                        sb.Append(FormatValue("Surname", 29));
                        sb.Append(FormatValue("Address", 39));
                        sb.Append(FormatValue("Country", 29));
                        sb.Append(FormatValue("DOB", 39));

                        //Last field does not matter
                        sb.Append(FormatValue("MaritalStatus", 9));


                    }
                    private static void CreateRow(Customer customer, StringBuilder sb)
                    {
                        /*
                           * 
                          Field            Position in the row
                          Name           1  
                          Surname          20
                          Address          50
                          Country          90
                          DOB              120
                          MaritalStatus    160

                           */
                        //First Field
                        sb.Append(FormatValue(customer.Name, 19));
                        sb.Append(FormatValue(customer.Surname, 29));
                        sb.Append(FormatValue(customer.Address, 39));
                        sb.Append(FormatValue(customer.Country, 29));
                        sb.Append(FormatValue(customer.DOB, 39));

                        //Last field does not matter
                        sb.Append(FormatValue(customer.MaritalStatus, 19));


                    }

                    private static string FormatValue(string value, int maxLength)
                    {
                        //TODO ADD OTHER STUFF HERE
                        return value.PadRight(maxLength, ' ');
                    }
                }

                public static class IOExtensions
                {
                    public static void WriteToFile(string text, string path)
                    {
                        using (var fs = File.CreateText(path))
                        {
                            fs.Write(text);
                        }
                    }
                }
                public class Customer
                {
                    public string Name { get; set; }
                    public string Surname { get; set; }
                    public string Address { get; set; }
                    public string Country { get; set; }
                    public string DOB { get; set; }
                    public string MaritalStatus { get; set; }
                }
            }

Upvotes: 3

Views: 975

Answers (4)

Zachary
Zachary

Reputation: 6532

I do this all the time, here is my suggestion.... Take your class and override the "ToString" function or create a custom function called something else. Use the "PadRight" string function to create fields of a fixed length with right padding.

Example (you'll need to add the rest of your fields to the ToString):

            public class Customer
            {
                public string Name { get; set; }
                public string Surname { get; set; }
                public string Address { get; set; }
                public string Country { get; set; }
                public string DOB { get; set; }
                public string MaritalStatus { get; set; }

                public override string ToString()
                {
                    return String.Format("{0}{1}{2}",
                        Name.PadRight(20),
                        Surname.PadRight(30),
                        Address.PadRight(40)
                        );
                }
            }

NOTE: We are using the length to control the starting position of each field. If the first filed is 20 characters, the next field will start at 21 and go to the length you define.

Now, loop over your data and fill your object and call customer.ToString() to write out the formatted string.

Upvotes: 2

Jim Mischel
Jim Mischel

Reputation: 133995

If you know how wide each column has to be, you can use String.Format to format the line. For example:

string s = String.Format("{0,-19}{1,-29}", customer.Name, customer.Surname);
sb.AppendLine(string);

Of course, your lines would be somewhat longer. But you can do it all in a single call.

A negative alignment value gives left alignment. A positive value gives right alignment in the field.

You could also use StringBuilder.AppendFormat.

See Composite Formatting for more information about formatting with either of those two methods.

The only drawback here is if the value you want to place in the field is longer than the field width. As the documentation says:

If the value of alignment is less than the length of the formatted string, alignment is ignored and the length of the formatted string is used as the field width.

Upvotes: 1

Mark Peters
Mark Peters

Reputation: 17755

It looks like the FileHelpers library would do the trick nicely. I've used it for CSV files, but it seems to handle fixed-width files as well.

Upvotes: 0

Arun
Arun

Reputation: 2523

Suggestions:

  • Customer object is not used in "CreateHeader()" method - remove it
  • Consider refactoring the WriteToFile() to handle a situation where you would find yourself iterating through a list or array of Customer objects. Would be better to write every Customer object separately as opposed to passing a big string

Upvotes: 0

Related Questions