Android Question Problem converting to map when reading list from file

kostefar

Active Member
Licensed User
Longtime User
Dear All,

If I read a JSON array from SQL:

B4X:
Dim Messages As List
Type Fivelines (msg_Subject As String,msg_Message As String, msg_Timestamp As String, msg_Sender As String, msg_threadid As String,msg_msgtype As Int,msg_username As String, msg_notify As String, msg_id As String, msg_count As String)
Dim Messages as List
Dim tl As Fivelines
Messages = parser.NextArray
If Messages.Size > 0 Then                         
                Dim i As Int
Dim m as Map
For i = 0 To (Messages.Size - 1)
m = Messages.Get(i)
tl.msg_subject = m.Get("subject")
msgbox (m,"")
next
File.WriteList(File.DirDefaultExternal, "/headers.txt", Messages)

(I excluded alot of code which I consider not relevant to explain this)

It all works well, and the file written to shows exactly what it should.
If I then afterwards use File.Readlist to read the file, it also looks good, BUT when I try to use the map object "m =" as above for the lines read from the file, I get:

java.lang.ClassCastException: java.lang.String cannot be cast to anywheresoftware.b4a.objects.collections.Map$MyMap

A look with msgbox at the lines in the file with the file show no difference between what´s being retrieved from the server, BUT if I use a msgbox, as in the above, to see what´s in the map object, the lines read from the server starts with "(MyMap)", whereas when they´ve been written to the file, they start with "(String)", and I´m positive that this is where the problem is. Any idea how this can be resolved?

Another weird thing is that the file is not written to the external sd card, but internally on the phone. This could be due to using an AVD emulator though, which however indeed is set up with a 2GB card.

Thanks in advance!
 

DonManfred

Expert
Licensed User
Longtime User
File.WriteList will write each item as a single line (which will be a string).
You should use another way of writing/loading the List of Types to a file.

Use Randomaccessfile lib for this.
Writing
B4X:
raf.WriteB4XObject(messages,0)
Reading
B4X:
Dim l As List = raf.ReadB4XObject(0)
 
Upvote 0

kostefar

Active Member
Licensed User
Longtime User

Thanks for your quick reply DonManfred. What I don´t get is that the list before it gets written, also consists of items that are single lines. What´s the difference other than that there seems to be a hidden identifier, one byte perhaps, making them seen as (String) rather than (MyMap) and should there not be a simple way to change this identifier?
 
Upvote 0

kostefar

Active Member
Licensed User
Longtime User
File.ReadList returns a List. Each item in the list is a String.

I'm not sure what you are looking for however the code posted by @DonManfred is very simple and will work properly (and is also cross platform).


Thanks Erel,


What I find odd is that:

I load items from a jsonarray into a List and save the list to a file. Processing the items from the list and getting map elements seperately in a map object works fine.
I load the items from the file into a list, which works great, and they each look the same as they did before they were saved. Each item can be assigned to a map element as before, but when trying to get map elements, the error occurs. This even if all the data looks the same, being a list with x number of items where nothing has changed in how the items look. The only tiny difference is when doing
msgbox (m,""), the word (String) shows before the rest of the content instead of (Mymap).

I´ve attached two images so that you can see what I mean.
 
Upvote 0

KMatle

Expert
Licensed User
Longtime User
I guess you did not really add maps to the list (as the message shows -> string).

How does Job.GetString look like? A list wth maps (JSON) looks like this (here 2 maps):

B4X:
[{"Action1":"Get1","MyUserPW":"Nothing","MyUsernummer":"Nothing","MyUserMail":"Nothing"}, {"Action2":"Get2","MyUserPW":"Nothing","MyUsernummer":"Nothing","MyUserMail":"Nothing"}]
 
Upvote 0

kostefar

Active Member
Licensed User
Longtime User

It looks like this, but I´m afraid DonManfred is right that this has nothing to do with JSON or httputils; the change occurs when the list has been written to a file, and then read again with ReadList. As a list, all looks identical, but when turned into a map, there´s that little MyMap/String difference:

B4X:
res = Job.GetString
        Log("Response from server: " & res)
        Dim parser As JSONParser
        parser.Initialize(res)       
        Dim Messages As List
        Messages = parser.NextArray
 
Upvote 0

kostefar

Active Member
Licensed User
Longtime User
Could you upload a little demo app? Just save & load the list WITH your data?

Thanks KMatle, but I think I´ll just put time into doing it the way suggested earlier instead. A shame that readlist works that way, and I think I get it now. Although already said, here´s with my own words:

Once a list has been written to a file with writelist, it will have datatype "string" for all its items, even if before that, the datatype was "mymap". This is why I get the error, and there seems to exist no way of converting something that´s labelled as a string to map, even if the content looks identical.
 
Upvote 0

KMatle

Expert
Licensed User
Longtime User
I've done a small test:

B4X:
Dim MyList As List
    Dim MyMap As Map = CreateMap("Key1":"Value1 ", "Key2":"Value2")
   
    MyList.Initialize
    MyList.Add(MyMap)
   
    File.WriteList(File.DirApp,"Test",MyList)
   
    MyList.Initialize
    MyMap.Initialize
   
    MyList=File.ReadList(File.DirApp,"Test")
    MyMap=MyList.Get(0)
    Log(MyMap)

It is really converted to a string :-(

@Erel: Is this a bug?

Then I did a quickcheck of my apps. I use RAF.Write/ReadObject.
 
Upvote 0

kostefar

Active Member
Licensed User
Longtime User

I kind of understand the logic. In a text file, you´ll be losing data types, so it all becomes strings. Writelist is not really good for anything that contains other kinds of content then. I tried with what DonManfred suggested, and although it takes a few more lines, it actually works pretty well!
 
Upvote 0

KMatle

Expert
Licensed User
Longtime User
This is the correct solution

I'm using RAF in all of my projects so I'm good. On the other hand I was expecting the List.WriteList method to write a list "as it is". But I was wrong. The documentation says it clearly ("will be converted to strings").
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
I was expecting the List.WriteList method to write a list "as it is"
If the list contains only simple strings then you are fine....
But working with Maps, Types in the list you better should use RAF to read/write the OBJECT
That´s why i answered this in post #2.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…