Android Question Strange behaviour of StringBuilder

Wosl

Member
I need some guidance on StringBuilder module. This function seems to be as simple as possible, but ...

The goal is to export data from internal structure 'PowerStrucX' to an external file in a CSV format to be able to import the data into MS Excel.

To get an appropriate Excel format I transform for each row each column with several operations (e.g. constant float point length, change decimal point to comma) into string variables (c1 to c17). This is all fine and works as expected. Because the data could be large I combine the each row and column with StringBuilder to one variable 'sb'. When 'sb' length exceeds a defined bufferlength, the variable is exported by appending to an existing file. The export itself works as expected (file management etc.) but the content is very strange.

StringBuilder:
Sub OutputCSVPower (cFileDir As String, cFileCSV As String, cExt As String, _
                    cDataType As String, PowerStrucX As PowerStruc) As ResumableSub
    Private nValues As Long, iFraction As Int, cReturn As String
    Private lTotalLength As Long, lLength As Long
    Private sb As StringBuilder, iJunk As Int
    Private c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17 As String

    '---------------------------------------------------------------
    '  Generate CSV Header and fraction of floating point numbers
    '---------------------------------------------------------------
    sb.Initialize
    If iPowerUnitIndicator = 0 Then
        iFraction = 1
    Else If iPowerUnitIndicator = 1 Then
        iFraction = 4
    Else If iPowerUnitIndicator = 2 Then
        iFraction = 7
    End If
    For i = 1 To nPowerTableName
        If i = 1 Then
            sb.Append(PowerTableName(i-1) & cExt)
        Else
            sb.Append(";" & PowerTableName(i-1) & cExt)
        End If
    Next
    sb.Append(CRLF)
    lTotalLength = sb.Length
    lLength      = lTotalLength

    '---------------------------------------------------------------
    ' Output header to new CSV file
    '---------------------------------------------------------------   
    Wait For (OpenOutputExternalStorage (cPVDataStorageFolder, cFileCSV, sb, False)) complete (oRes As Object)

    '---------------------------------------------------------------
    '  Loop through data rows
    '---------------------------------------------------------------
    nValues = PowerStrucX.TimestampList.Size
    If nValues < 1 Then
        Return "3"
    End If

    sb.Initialize
    iJunk = 0
    For i = 1 To nValues
        '  Setup row of data
        c1  = PowerStrucX.TimestampList.Get(i-1)
        c2  = PowerStrucX.DatumList.Get(i-1)
        c3  = ((RFormat(PowerStrucX.UhrzeitList.Get(i-1), 6, 14, True)).Trim).Replace(".",",")
        c4  = PowerStrucX.UhrzeitListText.Get(i-1)
        c5  = ((RFormat(PowerStrucX.UhrzeitListX.Get(i-1), 6, 14, True)).Trim).Replace(".",",")
        c6  = RFormat(PowerStrucX.ProduktionList.Get(i-1), iFraction, 8, True).Replace(".",",")
        c7  = RFormat(PowerStrucX.VerbrauchList.Get(i-1), iFraction, 8, True).Replace(".",",")
        c8  = RFormat(PowerStrucX.DirektverbrauchList.Get(i-1), iFraction, 8, True).Replace(".",",")
        c9  = RFormat(PowerStrucX.BatterieentladungList.Get(i-1), iFraction, 8, True).Replace(".",",")
        c10 = RFormat(PowerStrucX.NetzbezugList.Get(i-1), iFraction, 8, True).Replace(".",",")
        c11 = RFormat(PowerStrucX.NetzeinspeisungList.Get(i-1), iFraction, 8, True).Replace(".",",")
        c12 = RFormat(PowerStrucX.BatterieladungList.Get(i-1), iFraction, 8, True).Replace(".",",")
        c13 = RFormat(PowerStrucX.SpeicherladungList.Get(i-1), iFraction, 8, True).Replace(".",",")
        c14 = RFormat(PowerStrucX.WorkTodayList.Get(i-1), iFraction, 8, True).Replace(".",",")
        c15 = RFormat(PowerStrucX.WorkMonthList.Get(i-1), iFraction, 8, True).Replace(".",",")
        c16 = RFormat(PowerStrucX.WorkYearList.Get(i-1), iFraction, 8, True).Replace(".",",")
        c17 = RFormat(PowerStrucX.WorkTotalList.Get(i-1), iFraction, 8, True).Replace(".",",")

        sb.Append(c1).Append(";").Append(c2).Append(";").Append(c3).Append(";").Append(c4).Append(";").Append(c5).Append(";"). _
           Append(c6).Append(";").Append(c7).Append(";").Append(c8).Append(";").Append(c9).Append(";").Append(c10).Append(";"). _
           Append(c11).Append(";").Append(c12).Append(";").Append(c13).Append(";").Append(c14).Append(";").Append(c15).Append(";"). _
           Append(c16).Append(";").Append(c17).Append(";").Append(CRLF)
        'WOSL###########################
        Log ("Länge: " & sb.Length & " sb: " & sb.ToString)
        'WOSL###########################

        '  Append to external file
        lTotalLength = lTotalLength + sb.Length
        lLength = lLength + sb.Length
        If lLength > nStringBuffer Then
            AppendExternalStorage (sb.ToString)
            iJunk = iJunk + 1
            sb.Initialize
            lLength = 0
        End If

    Next

    '  Clear string buffer
    If lLength > 0 Then
        AppendExternalStorage (sb.ToString)
        iJunk = iJunk + 1
    End If
    sb.Initialize

    Log ("CSV File '" & cFileCSV & "' with power data (" & cDataType & ") successfully written to '" & _
          cFileDir & "' with " & lTotalLength & " Bytes in " & iJunk & " junks.")

    cReturn = "0"
    Return cReturn
End Sub

The log file looks like this ...
Log:
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create (first time) **
Can use persistant uri!
** Activity (main) Resume **
Get PV power data from SQLite DB on NAS, calculate work data and plot results
 
Generate 'Day' Chart (daily power flow chart in main activity)
TimestampFromToday, TimestampToToday, DateTime: T20250909000000, T20250909235959 (09.09.2025 00:00:00, 09.09.2025 23:59:59)
------------------------------------------------------------------
Get power data from webserver
Selected timeframe: T20250909000000 to T20250909235959
*** Receiver (httputils2service) Receive (first time) ***
Number of rows processed:    941
Länge: 171 sb:  17.9761T20250909000027;09.09.2025;0,007500;00:00:27;0,007500;  0,0000;  0,3138;  0,0000;  0,0000;  0,3138;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9761;
Länge: 171 sb:  17.9761T20250909000129;09.09.2025;0,024722;00:01:29;0,024722;  0,0000;  0,3120;  0,0000;  0,0000;  0,3120;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9761;
Länge: 171 sb:  17.9761T20250909000231;09.09.2025;0,041944;00:02:31;0,041944;  0,0000;  0,3106;  0,0000;  0,0000;  0,3106;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9761;
Länge: 171 sb:  17.9761T20250909000333;09.09.2025;0,059167;00:03:33;0,059167;  0,0000;  0,3408;  0,0000;  0,0000;  0,3408;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9761;
Länge: 171 sb:  17.9761T20250909000435;09.09.2025;0,076389;00:04:35;0,076389;  0,0000;  0,3111;  0,0000;  0,0000;  0,3111;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9761;
Länge: 171 sb:  17.9761T20250909000537;09.09.2025;0,093611;00:05:37;0,093611;  0,0000;  0,3394;  0,0000;  0,0000;  0,3394;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9761;
....

Depending on the selected string buffer length (i played around with this buffer) the file content shows all rows or only some.

However, two things are strange:
1. Each row starts with the content of the last string c17 ('17,9761'). It should start with a time stamp 'T20250909....'. When I delete c17 (use only c1 to c16) the string starts with the content of c16 ('0,6014')
2. The content of the file is incomplete (some times), which has nothing to do with the file operations but with the string buffer. I can skip the export but #1 is still wrong.

It seems that my implementation and usage of the StringBuilder variable 'sb' is wrong but I don't see the reason why.

It is nearly impossible to create a simple program to simulate the issue. I tried this (same sub, but some simulated data structure) and what happens: it worked!!

Any hint to overcome this issue is appreciated.

Wosl
 

emexes

Expert
Licensed User
Longtime User
My first thought is that you shouldn't have had to change the name of sb to sbEnh.

Your english is way better than my german, but just to head off a possible lost-in-translation issue that might otherwise cause insult:

I'm not saying you shouldn't have changed it. I'm saying that you shouldn't have needed to change it, and the fact that you put in the extra effort to change it when you didn't need to, makes me think that maybe there was an error or warning message when you first tried it without changing the name, that might help us discover what the heck is going on. 🍻
 
Upvote 0

Wosl

Member
We never give up :cool:

I decided to strip my app to build an isolated test program. With that everybody could run the StringBuilder test by its own. Any comments are appreciated.

What I found as mistakes / bad programming
- I declared the 'sb' Stringbuilder variable twice: in Process_Globals as global variable and in the sub as local variable. This should not be an issue but is bad programming. I deleted the local declaration.
- I declared in the resumable sub the return variable as 'int' but returned it as 'string'. This should provide an error but it didn't. The return declaration is now 'int'

I commented out all I/O operation subs (not relevant here). Here is the log
B4X:
Logger verbunden mit: R5CY13CHQ2W
--------- beginning of main
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create (first time) **
 Row 1:
  c(0), c(16)  = T20250911000033,  17,9971
  sb length = 171; sb:  17.9971T20250911000033;11.09.2025;0,009167;00:00:33;0,009167;  0,0000;  0,2836;  0,0000;  0,0000;  0,2836;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
 Row 2:
  c(0), c(16)  = T20250911000135,  17,9971
  sb length = 171; sb:  17.9971T20250911000135;11.09.2025;0,026389;00:01:35;0,026389;  0,0000;  0,2848;  0,0000;  0,0000;  0,2848;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
 Row 3:
  c(0), c(16)  = T20250911000237,  17,9971
  sb length = 171; sb:  17.9971T20250911000237;11.09.2025;0,043611;00:02:37;0,043611;  0,0000;  0,2875;  0,0000;  0,0000;  0,2875;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
 Row 4:
  c(0), c(16)  = T20250911000338,  17,9971
  sb length = 171; sb:  17.9971T20250911000338;11.09.2025;0,060556;00:03:38;0,060556;  0,0000;  0,2898;  0,0000;  0,0000;  0,2898;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
 Row 5:
  c(0), c(16)  = T20250911000440,  17,9971
  sb length = 171; sb:  17.9971T20250911000440;11.09.2025;0,077778;00:04:40;0,077778;  0,0000;  0,2844;  0,0000;  0,0000;  0,2844;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
CSV File '' with power data () successfully written to '' with 1110 Bytes in 1 junks.
** Activity (main) Resume **
 Row 1:
  c(0), c(16)  = T20250911000033,  17,9971
  sbEnh length = 162; sbEnh: T20250911000033;11.09.2025;0,009167;00:00:33;0,009167;  0,0000;  0,2836;  0,0000;  0,0000;  0,2836;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
 Row 2:
  c(0), c(16)  = T20250911000135,  17,9971
  sbEnh length = 324; sbEnh: T20250911000033;11.09.2025;0,009167;00:00:33;0,009167;  0,0000;  0,2836;  0,0000;  0,0000;  0,2836;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;T20250911000135;11.09.2025;0,026389;00:01:35;0,026389;  0,0000;  0,2848;  0,0000;  0,0000;  0,2848;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
 Row 3:
  c(0), c(16)  = T20250911000237,  17,9971
  sbEnh length = 486; sbEnh: T20250911000033;11.09.2025;0,009167;00:00:33;0,009167;  0,0000;  0,2836;  0,0000;  0,0000;  0,2836;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;T20250911000135;11.09.2025;0,026389;00:01:35;0,026389;  0,0000;  0,2848;  0,0000;  0,0000;  0,2848;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;T20250911000237;11.09.2025;0,043611;00:02:37;0,043611;  0,0000;  0,2875;  0,0000;  0,0000;  0,2875;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
 Row 4:
  c(0), c(16)  = T20250911000338,  17,9971
  sbEnh length = 648; sbEnh: T20250911000033;11.09.2025;0,009167;00:00:33;0,009167;  0,0000;  0,2836;  0,0000;  0,0000;  0,2836;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;T20250911000135;11.09.2025;0,026389;00:01:35;0,026389;  0,0000;  0,2848;  0,0000;  0,0000;  0,2848;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;T20250911000237;11.09.2025;0,043611;00:02:37;0,043611;  0,0000;  0,2875;  0,0000;  0,0000;  0,2875;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;T20250911000338;11.09.2025;0,060556;00:03:38;0,060556;  0,0000;  0,2898;  0,0000;  0,0000;  0,2898;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
 Row 5:
  c(0), c(16)  = T20250911000440,  17,9971
  sbEnh length = 810; sbEnh: T20250911000033;11.09.2025;0,009167;00:00:33;0,009167;  0,0000;  0,2836;  0,0000;  0,0000;  0,2836;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;T20250911000135;11.09.2025;0,026389;00:01:35;0,026389;  0,0000;  0,2848;  0,0000;  0,0000;  0,2848;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;T20250911000237;11.09.2025;0,043611;00:02:37;0,043611;  0,0000;  0,2875;  0,0000;  0,0000;  0,2875;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;T20250911000338;11.09.2025;0,060556;00:03:38;0,060556;  0,0000;  0,2898;  0,0000;  0,0000;  0,2898;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;T20250911000440;11.09.2025;0,077778;00:04:40;0,077778;  0,0000;  0,2844;  0,0000;  0,0000;  0,2844;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
CSV File '' with power data () successfully written to '' with 2685 Bytes in 1 junks.

The program has both, the standard (core) StringBuilder and the enhanced version, realized in two different subs.

The enhanced version comes up with the correct results.

I'm at the moment by end of my ideas to fix this issue.

Wosl
 

Attachments

  • Stringbuilder Test.zip
    4 KB · Views: 14
Upvote 0

Wosl

Member
I revised the attachment (not significantly) ... don't know how to delete the file in previous post
 

Attachments

  • StringBuilderTest.zip
    4.1 KB · Views: 14
Upvote 0

emexes

Expert
Licensed User
Longtime User
Is the stringfunctions library the original Margret edition, or one of the subsequent updates? Better yet, if you could post the actual library files (.jar and .xml, or .b4xlib), or the download post or link, that'd be great.

Never mind, seems to be working with Margret's version 1.05 from 2014, despite other advice to not use it anymore eg:

 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Longtime User
I'm at the moment by end of my ideas to fix this issue.

I coaxed my B4A system into 2025 and got it running with a spare phone, and now I I have your program running with the two different results.

Ripper! I am as happy as a pig in mud. But first I'll make a cup of tea, then get stuck into debugging. What could possibly go rwong?
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
Righto, I haven't fixed it, but... you were so close with:

I declared the 'sb' Stringbuilder variable twice: in Process_Globals as global variable and in the sub as local variable. This should not be an issue but is bad programming. I deleted the local declaration.

The problem is that you kept the global sb, which is also used in your PadText function, which leaves sb loaded with whatever last column data it was used on.

Found by adding sb.length logging, ie:

Log output:
Logger connected to:  HMD Global Nokia C01 Plus
--------- beginning of main
--------- beginning of system
** Service (starter) Start **
** Activity (main) Create (first time) **
sb length before = 8
sb length after = 171
 Row 1:
  c(0), c(16)  = T20250911000033,  17,9971
  sb length = 171; sb:  17.9971T20250911000033;11.09.2025;0,009167;00:00:33;0,009167;  0,0000;  0,2836;  0,0000;  0,0000;  0,2836;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
sb length before = 8
sb length after = 171
 Row 2:
  c(0), c(16)  = T20250911000135,  17,9971
  sb length = 171; sb:  17.9971T20250911000135;11.09.2025;0,026389;00:01:35;0,026389;  0,0000;  0,2848;  0,0000;  0,0000;  0,2848;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
sb length before = 8
sb length after = 171
 Row 3:
  c(0), c(16)  = T20250911000237,  17,9971
  sb length = 171; sb:  17.9971T20250911000237;11.09.2025;0,043611;00:02:37;0,043611;  0,0000;  0,2875;  0,0000;  0,0000;  0,2875;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;

and then doing a Ctrl+F of sb.append to find out what else in the program might be causing that "sb length before = 9"
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Longtime User
Righto, the fix is to delete the global sb, and then add Private sb As StringBuilder into the two Subs that complain about not having sb.

I got tripped up by another issue, which I think is that I used the first test zip that you provided. But once that was sorted, it's all good:

Log output:
Logger connected to:  HMD Global Nokia C01 Plus
--------- beginning of main
--------- beginning of system
** Service (starter) Start **
** Activity (main) Create (first time) **
sb length before = 0
sb length after = 163
 Row 1:
  c(0), c(16)  = T20250911000033,  17,9971
  sb length = 163; sb: T20250911000033;11.09.2025;0,009167;00:00:33;0,009167;  0,0000;  0,2836;  0,0000;  0,0000;  0,2836;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
sb length before = 163
sb length after = 326
 Row 2:
  c(0), c(16)  = T20250911000135,  17,9971
  sb length = 326; sb: T20250911000033;11.09.2025;0,009167;00:00:33;0,009167;  0,0000;  0,2836;  0,0000;  0,0000;  0,2836;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
T20250911000135;11.09.2025;0,026389;00:01:35;0,026389;  0,0000;  0,2848;  0,0000;  0,0000;  0,2848;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
 
sb length before = 326
sb length after = 489
 Row 3:
  c(0), c(16)  = T20250911000237,  17,9971
  sb length = 489; sb: T20250911000033;11.09.2025;0,009167;00:00:33;0,009167;  0,0000;  0,2836;  0,0000;  0,0000;  0,2836;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
T20250911000135;11.09.2025;0,026389;00:01:35;0,026389;  0,0000;  0,2848;  0,0000;  0,0000;  0,2848;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;
T20250911000237;11.09.2025;0,043611;00:02:37;0,043611;  0,0000;  0,2875;  0,0000;  0,0000;  0,2875;  0,0000;  0,0000;  0,0000;  0,0000;  0,2542;  0,6014; 17,9971;

including that the data is now collecting into multiple-line chunks.
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
On an unrelated note, your:

Sub PadText (psText As String, psCharacter As String, pnNewLength As Int, pbLeading As Boolean) As String

looks very similar to Margret StringFunctions:

Pad (Text As String, PadWith As String, Length As Int, Post As Boolean) As String


except that pbLeading and Post are coming at it from different ends, and Margret's Pad doesn't shrink down strings that are already longer than the specified length, but that's easy enough to fix the few instances where it's used, or you could use Margret's function to do most of the work inside your PadText routine.

B4X:
Sub PadText (psText As String, psCharacter As String, pnNewLength As Int, pbLeading As Boolean) As String
    '###############################################################
    '
    '  Format string to given length
    '
    '  psText        Text string
    '  psCharacter    Leading characters
    '  pnNewLength    Length of text string
    '  pbLeading    True: leading characters are filled with psCharacter
    '
    '################################################################

    Dim sf As StringFunctions
    
    Dim Temp As String = sf.Pad(       _
        psText,                        _
        (psCharacter & " ").CharAt(0), _
        pnNewLength,                   _
        Not(pbLeading)                 _
    )
    
    Return Temp.SubString2(0, pnNewLength)
End Sub
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Longtime User
Lol can't help myself - here's a bare-bones no-extra-library-required rendition of it:
B4X:
Sub PadText (psText As String, psCharacter As String, pnNewLength As Int, pbLeading As Boolean) As String
    '###############################################################
    '
    '  Format string to given length
    '
    '  psText        Text string
    '  psCharacter    Leading characters
    '  pnNewLength    Length of text string
    '  pbLeading    True: leading characters are filled with psCharacter
    '
    '################################################################

    If psText.Length > pnNewLength Then
        Return psText.SubString2(0, pnNewLength)    'trim to specified length
    Else If psText.Length = pnNewLength Then
        Return psText                               'is already specified length = no padding needed
    End If
   
    Dim PadChar As String = (psCharacter & " ").CharAt(0)
   
    Dim PadBuilder As StringBuilder
    PadBuilder.Initialize
    For I = psText.Length + 1 to pnNewLength
        PadBuilder.Append(PadChar)
    Next
   
    If pbLeading Then
        Return PadBuilder.ToString & psText    'padding before (leading)
    Else
        Return psText & PadBuilder.ToString    'padding after (post)
    End If
End Sub
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Lol can't help myself - here's a bare-bones no-extra-library-required rendition of it:
B4X:
Sub PadText (psText As String, psCharacter As String, pnNewLength As Int, pbLeading As Boolean) As String
    '###############################################################
    '
    '  Format string to given length
    '
    '  psText        Text string
    '  psCharacter    Leading characters
    '  pnNewLength    Length of text string
    '  pbLeading    True: leading characters are filled with psCharacter
    '
    '################################################################

    If psText.Length > pnNewLength Then
        Return psText.SubString2(0, pnNewLength)    'trim to specified length
    Else If psText.Length = pnNewLength Then
        Return psText                               'is already specified length = no padding needed
    End If
 
    Dim PadChar As String = (psCharacter & " ").CharAt(0)
 
    Dim PadBuilder As StringBuilder
    PadBuilder.Initialize
    For I = psText.Length + 1 to pnNewLength
        PadBuilder.Append(PadChar)
    Next
 
    If pbLeading Then
        Return PadBuilder.ToString & psText    'padding before (leading)
    Else
        Return psText & PadBuilder.ToString    'padding after (post)
    End If
End Sub
Now I have a terrible headache :mad:, but I'm curious to read this long thread.
For now, just a tiny, superfluous suggestion that definitely has nothing to do with the topic.

Write that nice parameter description before the routine signature, so they'll be visible in the contextual help.


B4X:
    '###############################################################
    '
    '  Format string to given length
    '
    '  psText        Text string
    '  psCharacter    Leading characters
    '  pnNewLength    Length of text string
    '  pbLeading    True: leading characters are filled with psCharacter
    '
    '################################################################
Sub PadText (psText As String, psCharacter As String, pnNewLength As Int, pbLeading As Boolean) As String

    If psText.Length > pnNewLength Then
'
'
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
You might like this too... is a surprisingly fast way to repeat a string (not necessarily just a single character):

B4X:
Sub RepeatString(S As String, L As Int) As String
    If S.Length = 0 Then Return RepeatString(" ", L)
    Do While S.Length < L
        S = S & S
    Loop
    Return S.SubString2(0, L)
End Sub
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
Lol can't help myself

You might like this too... a surprisingly fast way to repeat a string (not necessarily just a single character):

B4X:
Sub RepeatString(S As String, L As Int) As String
    If S.Length = 0 Then Return RepeatString(" ", L)    '[S]idiotproofing[/S] defensive programming
    Do While S.Length < L
        S = S & S
    Loop
    Return S.SubString2(0, L)
End Sub
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
You might like this too... is a surprisingly fast way to repeat a string (not necessarily just a single character):

B4X:
Sub RepeatString(S As String, L As Int) As String
    If S.Length = 0 Then Return RepeatString(" ", L)
    Do While S.Length < L
        S = S & S
    Loop
    Return S.SubString2(0, L)
End Sub
I think using StringBuilder in this will make it faster.

Why, if S is zero-length, do you return a string with L spaces? I think that's a mistake; if I wanted such a string, I would pass " ".
 
Upvote 0

Wosl

Member
SOLVED!

Just to sum it up as lessons learned:

The Stringbuilder variable 'sb' has been defined globally and locally in parallel. In general, this is possible, but needs to be used in a correct way. This bad mix results in a resetting and remaining string of 'sb' in the formatting sub 'PadText'.

The global usage of 'sb' is a relict of older times from another app where this logic was okay (and well implemented!). When eliminating the global definition the issue is solved.

What I learned:
- Don't just copy and past code segments without reviewing them in every detail
- Don't mix up global and local definitions of variables

Many thanks to emexes, who find the mistake, and to the B4x community to be patient with me.

Wosl
 
Upvote 0
Top