Android Question B4A: java.lang.ClassCastException: java.lang.String cannot be cast to b4a.exam

drgottjr

Well-Known Member
Licensed User
problem: an item in a list of custom type is being treated as type string
attached please find a snippet which reproduces the error

i have a list of (custom) type FAV which the user can select and add new entries to.
when the app launches, it tries to read in any previously saved list.
if there is no list (or no file containing the list), it creates a first entry for the list and writes the list to a file. so, if no additions are made to the list, the next time the user runs the app, there should be a single entry in the list, right?

this is the error when the user launches app and tries to access items in the list:
java.lang.ClassCastException: java.lang.String cannot be cast to b4a.example.main$_fav

so i go, wait - what string? i put together this snippet to duplicate the error.

1) to be safe, delete the saved list if it exists. if you're compiling for the first time, you can comment that out.
2) there is no initial list (or file), create the first entry, add it to the (empty) list, and save the list to disk.
3) app "confirms" that the list contains 1 entry. presumably it wrote 1 entry to disk...
4) exit

1) comment out line that deletes file
2) run app
3) since we know we saved 1 entry last time, read the list from disk
4) crash.

after creating and saving the first (and only) entry, i added a log comment to see what the app thought it was loading: 2 entries! so then i added a line of code and a couple log comments to see how many entries the app thought it was reading in right after it finished writing 1 entry. again 2.

i often use lists of custom types and assign the output from list.get() to an object of my type. i've never seen this error before. what am i missing here? i assume some blood from head banging has gotten into my eyes; i'm just not seeing it. tks.

-go
 

Attachments

  • ltest.zip
    372.5 KB · Views: 135

stevel05

Expert
Licensed User
File WriteList and Readlist is only meant for dealing with strings. To save and retrieve objects (your Type) you need to use B4XSerializator from the RandomAccesFile library.
 
Upvote 0

drgottjr

Well-Known Member
Licensed User
File WriteList and Readlist is only meant for dealing with strings. To save and retrieve objects (your Type) you need to use B4XSerializator from the RandomAccesFile library.

boink! boink! of course. thanks. i found my other "writelist"'s were to sqlite insert-into's... sorry.
 
Upvote 0

drgottjr

Well-Known Member
Licensed User
right, thanks. for me, a random access file is slightly different from what's in the randomaccessfile library.
the error i received has been addressed (with thanks), and i do see the library as a way to save/restore a list of objects. but i don't see it as permitting random access. is there, perhaps, another library?

what i'm referring to goes back to pre-historic, pre-sql times. (of course, the term "random" access is a misnomer, since the access is not random at all.) but, for me, random access meant i could position the file cursor at various parts of the data file (based on the size of the structure or record i was dealing with). among others, the options available involved positioning the file cursor with respect to the beginning of the file, the end of the file or the current position in the file. if the size of a structure used for each record in the database was 128 bytes (derived from a convenient sizeof() function), and i wanted to access the 10th record, i could simply position the cursor at 9 * 128 bytes from the start of the file and read 128 bytes to access that record. ditto for writing it back out.

with the randomaccessfile library, it seems to me that to correct the 10th record, i either have to read all the records in or at least read 10 in one at a time, step through the list until i get to the record i want, edit it, and then write the entire list back. even if i only read in 10 records and stopped, i would still have to write at least 10 records back (from the start of the file - a maneuver over which i have no control).

that said, i noticed that if i queried the current file position after appending a new record, it indirectly tells me what the size of my structure is, but that strikes me as an undocumented feature. in any case, and even if i could rely on that feature, i don't see any way to position the cursor (randomly) to access a given record based on it.
i can query the current file position. how do i set it?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
RandomAccessFile allows you to write or read data from any point in the file. This is less relevant if you are using WriteB4XObject as you will not know the size of each record.

If you prefer to work harder (without any benefit) then use the other lower level methods and serialize the data yourself. This is not needed unless there are many many items (maybe 100k+).
 
Upvote 0

drgottjr

Well-Known Member
Licensed User
if you want to see hard work without any benefit, watch joggers clutching their water bottles.
so, 2 questions:
1) if i can't know the size of a b4xobject, are you saying that i can know the size of a non-b4x object? if so, how?
2) if my custom type/record consists of only strings and integers, that qualifies it as a non-b4x object, right?

thanks again
 
Upvote 0

stevel05

Expert
Licensed User
I think to get what you want, you would have to use padded strings to make sure the records were all the same length.

Seems to me you have three alternative solutions:

1 - use an SQLite database.
2 - use the KeyValueStore Class (which implements an SQLite database)
3 - adding all to records to a Map and saving and loading the Map if it isn't going to be huge. (I'd choose option 1)
 
Last edited:
Upvote 0

drgottjr

Well-Known Member
Licensed User
while i disagree with erel's "lots of work without (any) benefit", he is - as usual - right. and you are too (option 1). the old timey random access (or relative) file was what i knew for so long. like the carpenter whose only tool is a hammer, i saw a solution through the claws of a hammer. erel is suggesting that what i was trying to do would work, as are you. but there are issues, and how much longer do i have anyway?
"padded strings" reminded me of punch cards; if you had a very long last name, it would be truncated in your record because the field had only been allotted 20 chars.

thanks to both for your input. i'm back in line now.
 
Upvote 0
Top