1

I've been trying to create a tab limited text file in c# so that the data are properly shown in separate columns.

Firstname       Lastname         Age
John            Smith            17
James           Sawyer           31

I have tried the "\t" character but all I get is this:

Firstname    Lastname    Age
John     Smith   17
James    Sawyer      31

Here is my code:

string[,] P = new string[2, 3] { 
                                    { "John", "Smith", "17" }, 
                                    { "James", "Sawyer", "31" } 
                                };

using (StreamWriter s_w = new StreamWriter(target))
{
    s_w.WriteLine("Firstname \t Lastname \t Age");

    for (int i = 0; i < 2; i++)
    {
        s_w.WriteLine("{0} \t {1} \t {2}", P[i,0], P[i,1], P[i,2]);
    }
}
Vahid
  • 4,369
  • 10
  • 55
  • 116

6 Answers6

4

Use string.Format and the composite formatting precision feature allows you to prepare your text in columns with the exact number of characters for each column

string[,] P = new string[2, 3] { 
                                    { "John", "Smith", "17" }, 
                                    { "James", "Sawyer", "31" } 
                                };

using (StreamWriter s_w = new StreamWriter(target))
{
    string row = string.Format("{0,-30}{1,-30}{2,10}", "Firstname", "Lastname", "Age");
    s_w.WriteLine(row);

    for (int i = 0; i < 2; i++)
    {
        row = string.Format("{0,-30}{1,-30}{2,10}", P[i,0], P[i,1], P[i,2]);
        s_w.WriteLine(row);
    }
}

this will align your data in three columns, the first is 30 characters wide and the text is aligned on the left, the same for the second column, while the third column is 10 characters wide and the data (age) is aligned on the right.

Of course to see an exact alignment of your column you need to look at your data using a fixed width font (Courier or Lucida Console for example) otherwise you will see disaligned columns, but this is due to the fact that in a variable width font the letter W needs more pixels in the horizontal than the letter i

Steve
  • 203,265
  • 19
  • 210
  • 265
  • This is the best answer. Combined with `\t` between the items, this would do everything the OP wanted. – Jeff Mar 03 '14 at 23:02
2

You can use PadRight like this:

 s_w.WriteLine("{0} \t {1} \t {2}", 
          P[i, 0].PadRight(10, ' '), 
          P[i, 1].PadRight(10, ' '), 
          P[i, 2].PadRight(10, ' '));

Note that the last PadRight is not necessary because it's the last column.There is no need to append anything to the right.Anyway if you have more properties then you need to use that too.

Selman Genç
  • 94,267
  • 13
  • 106
  • 172
  • 2
    I like this answer. I just posted my answer below, but think your solution is much more elegant that what I was planning (i.e., padding the strings with spaces, in a loop). Using .PadRight(...) is a good idea. – danyluis Mar 03 '14 at 22:48
1

What you are seeing is due to the way that tabs are displayed in the output. It looks correctly tab-delimited to me, it's just that the differing lengths cause the tabs to align to different tab-stops.

If this is to be viewed in a console, try using spaces for padding to pad each column to the same number of characters.

See the answers to this question for tips, but the gist is:

String.format("%10s", P[i,0]);

and so on for each of the others.

If it's actually supposed to be read as data, then leave as is, because it's correct now (although you probably want to remove the spaces in the string (i.e. "{0}\t{1}\t{2}".

Community
  • 1
  • 1
Jeff
  • 11,637
  • 5
  • 30
  • 56
  • Maybe I have used the incorrect terminology here. How can I get the column-delimited format shown above? – Vahid Mar 03 '14 at 22:44
  • As @danyluis says in their answer, how it is at the moment (but with the spaces removed in the string) is the way to go. If it's not displaying how you would like, try finding an editor with adjustable tab-stops (like how Word does it, though I'm not suggesting you use that...) – Jeff Mar 03 '14 at 22:51
1

Hi: If you absolutely need to use TAB characters (i.e., if you need to generate a file that can be easily read in Microsoft Excel, as a TAB-separated text file), then you're doing it correctly, because you're using only one TAB between every two columns. BUT, if what you want is to display the columns nicely spaced, then I suggest using spaces, instead of TAB characters. It's easier to manage. Search through all of your strings, find the widest string, assign this value plus 5, for example, and then layout your strings using that knowledge (i.e., adding as many spaces as needed to make all columns look aligned). If you need help with the code, I can post something later. But let me know, please.

danyluis
  • 86
  • 5
  • Thanks for the answer, actually I don't need to read it later, but I wondered if it is possible to have a nice looking file and be able to read it using Streamreader as well. Thanks for the clarification. – Vahid Mar 03 '14 at 22:49
1

I think you want to pad your data with spaces instead of tabs, which don't always line up:

s_w.WriteLine("Firstname           Lastname            Age");

for (int i = 0; i < 2; i++)
{
    s_w.WriteLine("{0,-20} \t {1,-20} \t {2}", P[i,0], P[i,1], P[i,2]);
}                     ^-- the -20 tells the formatter to left-align and pad to 20 characters
D Stanley
  • 139,271
  • 11
  • 154
  • 219
  • @D Stanley Using the padding value inside {,} seems elegant but the above code didn't work. Thanks – Vahid Mar 03 '14 at 22:56
-1

Selman22's answer completely did the job, here is another solution which is a little more concise:

string[,] P = new string[2, 3] { 
                                    { "John", "Smith", "17" }, 
                                    { "James", "Sawyer", "31" } 
                                };

using (StreamWriter s_w = new StreamWriter(target))
{
    s_w.WriteLine("{0,-15}  {1,-15}  {2,-15}","Firstname", "Lastname" ,"Age");

    for (int i = 0; i < 2; i++)
    {
        s_w.WriteLine("{0,-15}  {1,-15}  {2,-15}", P[i, 0], P[i, 1], P[i, 2]);
    }
}
Vahid
  • 4,369
  • 10
  • 55
  • 116