Android Question saving and loading lists with respect to data type

tmf

Member
Licensed User
Longtime User
So I have a list

dim list1 as list

then I add 3 booleans

list1.add(false)
list1.add(true)
list1.add(false)

then I save the list

File.WriteList(File.DirDefaultExternal, "mylist", list1)

then later I read the list

list1.clear()
list1 = File.ReadList(File.DirDefaultExternal, "mylist")

My issue is it seems this list is now of type String and not boolean

How do people deal with this??

I searched and found no answers.

Richard.
 

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
That is how the read/write list method is supposed to behave. You need to use the WriteB4XObject/ReadB4XObject (found in the RandomAccessFile library) if you wish to preserve the data types.
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
If you want the functionality of the original methods, you can always wrap the other methods, something like:
B4X:
Public Sub WriteTypedList(Directory As String, Filename As String, TheList As List)    ' requires RandomAccessFile library
    Dim poRaf As RandomAccessFile
    poRaf.Initialize(Directory, Filename, False)
    poRaf.WriteB4XObject(TheList, 0)
    poRaf.Close
End Sub

Public Sub ReadTypedList(Directory As String, Filename As String) As List
    Dim poList As List

    poList.Initialize
    If File.Exists(Directory, Filename) Then
        Try
            Dim poRaf As RandomAccessFile
            poRaf.Initialize(Directory, Filename, True)
            poList = poRaf.ReadB4XObject(0)
            poRaf.Close
        Catch
            Log(LastException)
        End Try
    End If

    Return poList
End Sub
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
It started with a "list of strings".
File.WriteList was written for such "lists".

But i really cant answer WHY. I just know that it will not work for Lists containing others than just string.
So i use RandomAccessFile.

Due to the different objecttypes a list can hold (or a Map) randomaccessfile takes the job (and today writeb4xobject is compatible with b4a, b4i and b4j.

Using File.Writelist is probably the wrong solution for lists like yours.
 
Upvote 0

tmf

Member
Licensed User
Longtime User
Yes I just modded my code similar below and all good! I just always use offer 0 as I only have one thing I am saving, thanks guys!

Dim raf As RandomAccessFile

' read
If(File.Exists(File.DirDefaultExternal, "moduleiplist")) Then
moduleIP.Clear
raf.Initialize(File.DirDefaultExternal, "moduleiplist", False)
moduleIP = raf.ReadB4XObject(0)
raf.Close()
loaded = True
End If

' write
raf.Initialize(File.DirDefaultExternal, "moduleiplist", False)
raf.WriteB4XObject(moduleIP, 0)
raf.Close
 
Upvote 0

tmf

Member
Licensed User
Longtime User
oh one thing, I am ASSUMING :) that raf.Initialize(File.DirDefaultExternal, "moduleiplist", False) overwrite the file "moduleiplist" as it seems to work fine each time its saved and re-read....

RichardS
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Dim raf As RandomAccessFile
You can spare yourself the use of additional overhead from using the RAF lib by using a map:
B4X:
Private map As Map
    map.Initialize
    map.Put("0",False)
    map.Put("1",True)
    map.Put("2",False)
    File.WriteMap(File.DirRootExternal,"mapfile",map)

'Read:
    Dim m As Map
    m.Initialize
    m=File.ReadMap(File.DirRootExternal,"mapfile")   
    Dim b As Boolean = m.Get("1")
    Log("I am  " & b)
 
Upvote 0

tmf

Member
Licensed User
Longtime User
If you want the functionality of the original methods, you can always wrap the other methods, something like:
B4X:
Public Sub WriteTypedList(Directory As String, Filename As String, TheList As List)    ' requires RandomAccessFile library
    Dim poRaf As RandomAccessFile
    poRaf.Initialize(Directory, Filename, False)
    poRaf.WriteB4XObject(TheList, 0)
    poRaf.Close
End Sub

Public Sub ReadTypedList(Directory As String, Filename As String) As List
    Dim poList As List

    poList.Initialize
    If File.Exists(Directory, Filename) Then
        Try
            Dim poRaf As RandomAccessFile
            poRaf.Initialize(Directory, Filename, True)
            poList = poRaf.ReadB4XObject(0)
            poRaf.Close
        Catch
            Log(LastException)
        End Try
    End If

    Return poList
End Sub

How critical is the TRY/CATCH?

RichardS
 
Upvote 0

tmf

Member
Licensed User
Longtime User
taking this one more step...

I made a array of lists

dim presets(10) as list

then I do things like adding strings to the lists

presets(0).add("item")

then I try and save presets to a file in short:
raf.WriteB4XObject(presets, 0)

then read it back
presets = raf.ReadB4XObject(0)

However now my code does not like this "new" presets, but before the save and load it was fine.

The docs say lists can be arrays and strings and a combo of both.

RichardS
 
Upvote 0

tmf

Member
Licensed User
Longtime User
sorry for small error above

presets(0).add("item") should be presets(0).add(numbers)

numbers is an array of strings

java.lang.ClassCastException: java.lang.Object[] cannot be cast to java.lang.String[]

when you do:
numbers = presets.Get(position)

RichardS
 
Upvote 0

tmf

Member
Licensed User
Longtime User
Sorry really messing up here!

presets is a list, plain and simple

I do presets.add(numbers) and

numbers = presets.get(0) gives me grief

numbers before the save/load worked fine

and numbers is still an array of string

RichardS
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
I'm not sure, as I understand the write object that should work. I've never tired writing an object like that, I try to keep things simple. If I need lists of lists I will generally design a class to handle it.

You might try saving each entry individually and see if you get better results, such as:
B4X:
. . .
raf.WriteB4XObject(presets(0), 0))
raf.WriteB4XObject(presets(1), raf.CurrentPosition)
raf.WriteB4XObject(presets(2), raf.CurrentPosition)
. . .
. . .
presets(0) = raf.ReadB4XObject(0)
presets(1) = raf.ReadB4XObject(raf.currentposition)
presets(2) = raf.ReadB4XObject(raf.currentposition)
. . .
How critical is the TRY/CATCH?
I'm old, so I "grew up" with unreliable mapped network connections, drives that gave the odd I/O error and so on therefore wrapping any kind of disk I/O in a try/catch block is like a nervous tick for me.

How critical it is here would be a question better answered by Erel ;)
 
Last edited:
Upvote 0

tmf

Member
Licensed User
Longtime User
Thanks, I was hoping not to do it that way, but its OK... I can iterate through a loop :)

Yeah I am "old" too :)

I just want to add all I can to make my app not crash in the field :)

RichardS

I'm not sure, as I understand the write object that should work. I've never tired writing an object like that, I try to keep things simple. If I need lists of lists I will generally design a class to handle it.

You might try saving each entry individually and see if you get better results, such as:
B4X:
. . .
raf.WriteB4XObject(presets(0), 0))
raf.WriteB4XObject(presets(1), raf.CurrentPosition)
raf.WriteB4XObject(presets(2), raf.CurrentPosition)
. . .
. . .
presets(0) = raf.ReadB4XObject(0)
presets(1) = raf.ReadB4XObject(raf.currentposition)
presets(2) = raf.ReadB4XObject(raf.currentposition)
. . .

I'm old, so I "grew up" with unreliable mapped network connections, drives that gave the odd I/O error and so on therefore wrapping any kind of disk I/O in a try/catch block is like a nervous tick for me.

How critical it is here would be a question better answered by Erel ;)
 
Upvote 0
Top