Android Question Exception while converting List to ByteArray

artsoft

Active Member
Licensed User
Longtime User
Hi all!

I have a question:

This thread https://www.b4x.com/android/forum/threads/how-to-convert-list-to-byte-array.67303/ explains on how to convert a normal list into a byte array.

@Erel provided this simple method for that:
B4X:
Sub ListToBytes(list As List) As Byte()
   Dim b(list.Size) As Byte
   For i = 0 To list.Size - 1
     b(i) = list.Get(i)
   Next
   Return b
End Sub

But, what happens if each entry in the list object has more than 1 byte.

Example:
My list contains 4 entries.
Each entry has such a content: "Hello World".
The list.size is 4 and the target byte array has only a size of 4 bytes.

This makes sense, because - while using this method - I get always this error:

B4X:
Error occurred on line: 613 (Tools)
java.lang.NumberFormatException: For input string: "[B@15041a8"
    at jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
    at jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
    at java.lang.Double.parseDouble(Double.java:543)
    at anywheresoftware.b4a.debug.RDebugUtils.numberCast(RDebugUtils.java:63)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:265)
    at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resumeAsUserSub(DebugResumableSub.java:48)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:205)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resume(DebugResumableSub.java:43)
    at anywheresoftware.b4a.keywords.Common$14.run(Common.java:1748)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:210)
    at android.os.Looper.loop(Looper.java:299)
    at android.app.ActivityThread.main(ActivityThread.java:8168)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1037)

And line 613 is this one:
B4X:
b(i) = list.Get(i)

Is there something missing?
Or should I cast something to another type?

Perhaps somebody can help here.

Additional information:
My list object contains data from Audiostreamer (see example for recording audio data). In this example a normal list is used as "audiobuffer".

Regards and thanks in advance
ARTsoft
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
While using this method

The list in that thread ONLY contains ONE Character in each entry. For THIS List you can use that Method.
how to convert a normal list into a byte array
Only if the List only contains single Bytes.

I can´t see what you are doing there. Upload a small project showing your issue. This can help much in understanding what you are doing.
 
Upvote 0

artsoft

Active Member
Licensed User
Longtime User
The list in that thread ONLY contains ONE Character in each entry. For THIS List you can use that Method.

Only if the List only contains single Bytes.

I can´t see what you are doing there. Upload a small project showing your issue. This can help much in understanding what you are doing.

Thanks DonManfred :)

Yes, this was also in my opinion.

What I need is a method which extract each (String) entry in the list in order to interate each byte in this string - in order to save each byte in the target byte array.

Is there already such a method in B4A which does the same?
Or should I create my own method?

Regards
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
It is a bit unclear what exactly you are trying to archieve.

What I need is a method which extract each (String) entry
which STRING?

Additional information:
My list object contains data from Audiostreamer

Data from Audiostreamer are binary-data and not Strings.
To collect the bytes you should use
B4X:
list.AddAll(bytesfromaudiostreamer) ' Where list is your Listobject...
 
Upvote 0

artsoft

Active Member
Licensed User
Longtime User
It is a bit unclear what exactly you are trying to archieve.


which STRING?



Data from Audiostreamer are binary-data and not Strings.
To collect the bytes you should use
B4X:
list.AddAll(bytesfromaudiostreamer) ' Where list is your Listobject...

Absolutely right, DonManfred! Bad wording :-( using the word String - I mean the bytes.
My mistake!

The audio streaming data (after a sound recording) is already (!) saved in a list object (see below 'audioBuffer').
So there is no need to use "AddAll" method.

There is an AudioStream example in this forum and I used this in order to see on how the developer recorded some audio data:

B4X:
Private audioBuffer As List

Private Sub streamer_RecordBuffer (Buffer() As Byte)
  
    audioBuffer.Add(Buffer)   ' audioBuffer is a list object!
  
End Sub

So the following action is now to convert all data (saved in audioBuffer list) into a simple byte array.

Thanks and regards
 
Last edited:
Upvote 0

artsoft

Active Member
Licensed User
Longtime User
This is the method for converting a byte array to a normal list (as you said using the AddAll method):

B4X:
Public Sub ByteArrayToList (b() As Byte) As List

    Dim retList As List : retList.Initialize

    retList.AddAll(b) 
  
    Return retList

End Sub

And for the other direction I need also a method:

And based on the fact, that the "streamer_RecordBuffer" callback method (see above) always adds a new byte array to the list, there is a need to have the other method to convert such a list (filled with byte arrays!) back into a onyl 1 (big) byte array.

I tried this - but I think this is wrong:

B4X:
Public Sub ListToBytes(list As List) As Byte()
  
    Dim count As Int = 0
  
    For Each b() As Byte In list
        count = count + b.Length
    Next
  
    Dim retB(count) As Byte
  
    Dim seek As Long = 0
    Dim b() As Byte
  
    For i = 0 To list.Size - 1
        b = list.Get(i)
        If (b.Length > 0) Then
            For j = 0 To b.Length-1
                retB(seek + j) = b(j)
            Next
            seek = seek + b.Length
        End If
    Next

    Return retB
  
End Sub

Firstly I detect the complete lengths of all byte arrays in the list in order to summarize these.

With this complete length I create the byte array "retB".

Then I copy (byte by byte) each byte to the target byte arry. But I guess there is a better method ... a quicker method ... to do this!

Regards
 
Upvote 0

artsoft

Active Member
Licensed User
Longtime User
B4X:
    Dim newbytes(10) As Byte ' Image this is your bytearray from the audiostreamer.
   
    Dim l As List ' Image this is your capturebuffer-List
    l.Initialize
    l.AddAll(newbytes)
    Log(l.Size) ' Logs 10

Creating a new List is not mandatory.

Dear DonManfred!

This code is ok - but I need the "other" way ... the "other" direction -->

Public Sub ListToBytes(list As List) As Byte()
...
End Sub

I have a list with entries, each entry is a byte array:

B4X:
List has 5 entries:

|-------1------|-------2------|-------3------|-------4------|-------5-----|
|b(0)|b(1)|b(2)|b(0)|b(1)|b(2)|b(0)|b(1)|b(2)|b(0)|b(1)|b(2)|b(0)|b(1)|b(2)
|--------------|--------------|--------------|--------------|-------------|

Each entry has 3 bytes.

The goal is to have a byte array with 15 bytes.

Unfortunately this code doesn't work properly:

B4X:
Public Sub ListToBytes(list As List) As Byte()
    
    Dim o As OutputStream
    
    o.InitializeToBytesArray(0)

    Dim b() As Byte
    
    For i = 0 To list.Size - 1
        b = list.Get(i)
        o.WriteBytes(b, 0, b.Length)
    Next
    
    Dim retB() As Byte = o.ToBytesArray
    
    o.Close

    Return retB
    
End Sub

Thanks a lot DonManfred for your help!

Regards
 
Upvote 0
Top