Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I format a string into a fixed width field in .Net?

Tags:

.net

vb.net

I am trying to format a string of arbitrary length into a fixed width field for display.

Let's use a width of 20 as an example, and call the string to be formatted s. I'm adding the formatted string to a StringBuilder named b.

Dim b As New System.Text.StringBuilder()
Dim s as New String

If the string I want to display is shorter than 20 characters, I can do this:

b.Append(s.PadRight(20))

or

b.AppendFormat("{0,-20}", s)

So far, so good. But, if the string is longer than 20 characters, I want the string to be truncated to 20 characters as it is appended. The code above appends the entire string.

I tried this:

b.Append(s.Substring(0,20).PadRight(20))

But, this fires an exception if the string was shorter than 20 characters.

So, I ended up with:

b.Append(s.PadRight(20).Substring(0,20))

This seems to do the job. The PadRight prevents the exception by making sure thet string has 20 characters before the Substring is performed.

I was wondering if there is an alternate method that would look more elegant and avoid padding the string just so prevent the substring from causing an exception. Have I missed a feature of String.Format that can accomplish this in one step?

Edited to add solution:

I ended up with the following code:

Module Extensions
    <Extension()> _
    Function AppendFixed(ByVal b As StringBuilder, ByVal s As String, ByVal width As Integer) As StringBuilder
        If s.Length >= width Then
            b.Append(s, 0, width)
        Else
            b.Append(s)
            b.Append(" ", width - s.Length)
        End If
        Return b
    End Function
End Module

This uses an extension method to clean up the syntax, as suggested by Joel and Merlyn, and uses the StringBulider Append overloads to avoid creating new strings that will have to be garbage collected, as suggested by supercat. Thanks to those that helped.

like image 315
B Pete Avatar asked Aug 01 '11 21:08

B Pete


3 Answers

I was wondering if there is an alternate method that would look more elegant and avoid padding the string

(emphasis added)

<Extension()> _
Public Function AppendFixed(ByVal target As StringBuilder, ByVal value As String, ByVal desiredLength As Integer) As StringBuilder
    If value.Length < desiredLength Then value.PadRight(desiredLength)
    Return target.Append(value.Substring(0,desiredLength))
End Function

To use it:

b.AppendFixed(s, 20)
like image 102
Joel Coehoorn Avatar answered Nov 19 '22 08:11

Joel Coehoorn


I don't think there is a more elegant way to do this. Though you could wrap this functionality into an extension method:

Imports System.Runtime.CompilerServices

Module StringExtensions

    <Extension()> _
    Public Function AsFixedWidth(ByVal value As String, desiredLength As Integer) As String
        return value.PadRight(desiredLength).Substring(0,desiredLength)
    End Function

End Module

And use it like this:

b.Append(s.AsFixedWidth(20))
like image 44
Merlyn Morgan-Graham Avatar answered Nov 19 '22 08:11

Merlyn Morgan-Graham


I would suggest that to minimize strain on the garbage collector, one should handle separately the cases where one needs to return a string from those where one needs to append a string to a StringBuilder. One should also separate out the cases where the string to be appended is shorter than needed, precisely the desired length, or longer than needed.

If one needs to return a string that's the same length as the original, just return the original string. If the string needs padding, pad it with a New String(' ', requestedLength - theString.Length). If it needs to be made shorter, return theString.Substring(0, requestedLength).

If one needs to append something to a StringBuilder and the original string is no longer than needed, append the string and then use the (char, int) overload of Append to add padding if needed. If the original string is too long, use the (String, int, int) overload of Append to add just the proper portion.

like image 2
supercat Avatar answered Nov 19 '22 08:11

supercat