Android Question [Solved ] Extract text line by line from TextField

Roger Daley

Well-Known Member
Licensed User
Longtime User
Hi All,

I am looking for the simplest way to extract text line by line from a TextField.

Below is dummy code as an attempt to show what I am trying to achieve. Something like "TextReader" on text files.

Example:
Sub Process_Globals
Private LineX As String
End Sub

Sub Globals
Private txtField As B4XFloatTextField
End Sub

Sub ReadLines
        For j = 0 To 999                          
           LineX  = txtField.line(j)                     'Get one line from the textfield
              
           'Put Linex in an array of strings and other stuff.

            If LineX = "EndPlay"  Then Exit        'EndPlay indicates end of file.

           'Now loop and get next line from the textfield.

        Next
End Sub


Regards Roger
 
Last edited:

Alan Doucet

Member
Licensed User
Hi Roger,

Here's a little sub I used to save an updatable text file for a little testing app I did a while back. Very simple and fixed data set. Hope it helps.

Sub HistBuild

Dim HistSTG As String
Dim HStart As Int = 0
Dim HEnd As Int = 17

HistStage = File.ReadString(File.DirInternal, "H1.txt")

HistSTG = HistStage

For X = 0 To 28

HistSTG = HistStage.SubString2(HStart,HEnd)

History01(X,0) = HistSTG.SubString2(0,2)
History01(X,1) = HistSTG.SubString2(2,5)
History01(X,2) = HistSTG.SubString2(5,9) 'Times Answered
History01(X,3) = HistSTG.SubString2(9,13) 'Times Correct
History01(X,4) = HistSTG.SubString2(13,17) 'Times Wrong

HStart = HStart + 18
HEnd = HEnd + 18

Next

End Sub
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
the simplest way to extract text
I know you are pretty particular, but why does it have to be that complicated. What about this:
B4X:
Dim et1 As EditText = B4XFloatTextField1.TextField
If et1.Text.Contains("EndPlay") Then   'or EndsWith
        Log("yes")       
    End If
Or maybe for each l as string in file.readlist....
 
Upvote 0

Roger Daley

Well-Known Member
Licensed User
Longtime User
Mahares,

My fault, my dummy code didn't make it clear what I was after. I have modified the first post, hopefully for the better.
I tried to use File.Readlist (Dir As String, FileName As String) As List, but couldn't fit txtField.TextField into (Dir As String, FileName As String).

Thanks for the feedback.

Roger
 
Upvote 0

emexes

Expert
Licensed User
Bonus:

"\n+" should remove interior blank lines at the same time, by treating consecutive newlines as a single separator rather than as individual/multiple separators.

"+" is quantifier to match the preceding newline character "\n" one or more times.
 
Last edited:
Upvote 0

Roger Daley

Well-Known Member
Licensed User
Longtime User
Bonus:

"\n+" should remove blank lines at the same time, by treating consecutive newlines as a single separator rather than as individual/multiple separators.

"+" is quantifier to match (preceding) character one or more times.

emexes,
Many thanks.
I haven't been able to try Erel's code yet. This evening's job.

In my case the blank lines are important and have to remain.
Good to know for future use.

Once again many thanks.

Roger
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Although Regex is very versatile, isn't more intuitive to use: CRLF instead of \n or \n+. One would remember more easily the first than the other two notations.
I haven't been able to try Erel's code yet
Out of curiosity, why are you trying to display a scrollable list on a B4XFloatTextField when there are better and more practical options like B4XSearchTemplate or B4XListTemplate. Perhaps you have a valid reason.
 
Upvote 0

Roger Daley

Well-Known Member
Licensed User
Longtime User
Although Regex is very versatile, isn't more intuitive to use: CRLF instead of \n or \n+. One would remember more easily the first than the other two notations.

Out of curiosity, why are you trying to display a scrollable list on a B4XFloatTextField when there are better and more practical options like B4XSearchTemplate or B4XListTemplate. Perhaps you have a valid reason.
Marhares, long story.
I have a Calculator App which can define new functions and assign the function to a key. [Basically a keystroke recorder.] The steps of each function are recorded in an array of strings.
For export/import I have previously saved/loaded the array as a text file in the Download folder. With the coming changes to accessing Secondary Memory and the surrounding confusion, I removed the export/import functions from the calculator.

With Erel's Texteditor example it showed me a solution. B4XFloatTextField saves/loads text files to the SD Card, the text in the B4XFloatTextField can be stored in the array of strings, the text in the array of strings can be loaded into the B4XFloatTextField . A round about way of transferring programmed functions in and out of the App so that they can be shared with other users/devices. I hope this makes sense.

There are probably better ways to achieve this like B4XSearchTemplate or B4XListTemplate but I have fallen way behind on such things.

Regards Roger
 
Upvote 0

Roger Daley

Well-Known Member
Licensed User
Longtime User
Hi All,

It looks like I celebrated too early. I have finally found time to try Erel's suggestion #5, unfortunately without success.

Below is the "Sub HandleLoadResult(Result", I have added code to log the entry's in the List "LINES". Further below is the Log which shows no text in each line despite showing correctly in the texteditor. I have also attached the text file I was using for testing.

Have I misinterpreted something?

Regards Roger



B4X:
Private Sub HandleLoadResult(Result As LoadResult)
    If Result.Success Then
        Dim s As String
        Try
            s = File.ReadString(Result.Dir, Result.FileName)
            toast.Show($"File '${Result.RealName}' loaded"$)   
        Catch
            s = "Error loading file"
            Log(LastException)
        End Try
        txtField.Text = s
        
        
        '*********** Added Code ************
        Private LineText As Int
        Private Lines As List
            
        Lines.Initialize
        Lines = Regex.Split("\n", txtField.Text)                    'Loads the Text from the texteditor to the LIST Lines.
            
        Log(Lines.Size)
        For EP = 0 To Lines.Size-1
            LineText = Lines.IndexOf(EP)
            Log(LineText)
        Next
        '*********************************************************************** 
    End If
End Sub

** Activity (main) Resume **
** Activity (main) Pause event (activity is not paused). **
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
** Activity (main) Resume **
** Activity (main) Pause event (activity is not paused). **
sending message to waiting queue (OnActivityResult)
running waiting messages (1)
** Activity (main) Resume **
14
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
** Activity (main) Pause event (activity is not paused). **
 

Attachments

  • XCube.txt
    67 bytes · Views: 194
Upvote 0

Roger Daley

Well-Known Member
Licensed User
Longtime User
emexes thanks,

I read over that many times without seeing it.
I have changed the line to:
B4X:
LineText = Lines.Get(EP)


However it now crashes this line with Log Error:
** Activity (main) Create, isFirst = true **
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
** Activity (main) Resume **
** Activity (main) Pause event (activity is not paused). **
sending message to waiting queue (OnActivityResult)
running waiting messages (1)
** Activity (main) Resume **
5
b4xmainpage_handleloadresult (java line: 153)
java.lang.NumberFormatException: For input string: "line2"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
at anywheresoftware.b4a.BA.ObjectToNumber(BA.java:684)
at b4a.example.b4xmainpage._handleloadresult(b4xmainpage.java:153)
at b4a.example.b4xmainpage$ResumableSub_Load.resume(b4xmainpage.java:216)
at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:267)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:207)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:193)
at anywheresoftware.b4a.keywords.Common$14.run(Common.java:1770)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8506)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1139)

It looks like I am back to square one.:confused:

Regards Roger
 
Upvote 0
Top