Conversion problem

HotShoe

Well-Known Member
Licensed User
Longtime User
I find myself pulling out hair over an update I am doing. I have a typed record/structure that is used to store information into individual vehicle files in Virtual Dyno. I use the randomaccessfile object to do this. It has always worked flawlessly until this update.

I have had to add to the record/structure stored to the card, so I did just like I have thousands of time before. I renamed the old structure and used a copy of it to add the new fields. The structures are below.

B4X:
Type vdrecord(metric As Boolean, spress, icenter, ecenter, idur, edur, weight As Short, ilift, elift As Double, head, _
   extype As Byte, vtech As Boolean, fueltyp, no2, ecm, posi, susptype, tire, itype, ltype, boost, trans As Byte, _
   dish, ccv, twidth, rock, hgv, idia, edia, ratio, bore, stroke, radius, p2d As Double, cyl, rod, ign, bal, _
   blower As Byte, blowcfm As Short, vcyl As Byte, rodlen As Double, carbtype As Byte, intcfm, excfm, intvol, _
   exvol As Double, ohc As Boolean, overlap As Short, spare1, spare2, spare3 As Double)
   
   Type oldvdrecord(spress As Int, icenter As Int, ecenter As Int, idur As Int, edur As Int, ilift As Int, _
   elift As Int, weight As Int, head As Byte, extype As Byte, vtech As Boolean, fueltyp As Byte, no2 As Byte, _
   ecm As Byte, posi As Byte, susptype As Byte, tire As Byte, itype As Byte, ltype As Byte, boost As Byte, _
   trans As Byte, dish As Double, ccv As Double, twidth As Double, rock As Double, hgv As Double, idia As Double, _
   edia As Double, ratio As Double, bore As Double, stroke As Double, radius As Double, p2d As Double, cyl As Byte, _
   rod As Byte, ign As Byte, bal As Byte, blower As Byte, blowcfm As Int, vcyl As Byte, rodlen As Double, carbtype As Byte)

Yes they are largish, but they serve my purpose. The new update needs to be able to read the old format (oldvdrecord) to convert existing filles. The problem is that it doesn't do that. It writes/reads the new structure just fine, but it refuses to read the old structure. Here are the read routines.

B4X:
Sub loadfile
   Dim vfile As RandomAccessFile
   
   If filenam = "" Then
   Return
   End If
   
   If importing Then
   vfile.Initialize(File.DirRootExternal,"/download/"&filenam, False)
   Else
   vfile.Initialize(datadir,filenam, False)
   End If
   
   Try
   vrec= vfile.ReadObject(0)
   Catch
   vfile.Close
   loadoldfile
   
   Return
   End Try

   vfile.Close
   
   init_fields   
   
End Sub

Sub loadoldfile
   Dim ovfile As RandomAccessFile
   
   If importing Then
   ovfile.Initialize(File.DirRootExternal,"/download/"&filenam, False)
   Else
   ovfile.Initialize(datadir,filenam, False)
   End If
   
   Try
   oldvrec.Initialize
   'oldvrec.spress= ovfile.ReadInt(0)
   
   oldvrec= ovfile.ReadObject(0)
   oldvrec_to_vrec
   
   Catch
   Msgbox("This file appears to be corrupted!","Error")
   Log(LastException)
   ovfile.Close
   init_fields
   
   Return
   End Try

   ovfile.Close
   
   init_fields   
   
End Sub
vrec is the new structure (vdrecord) and oldvrec is the old structure (oldvdrecord). If the loadfile routine fails, it calls the loadoldfile sub and tries loading it as the old format before displaying an error. Now I know the old record works. It was lifted from running code. In fact, I can run the earlier version and it loads the old files flawlessly. So why can't I get this to work?

I am getting a "(IllegalArgumentException) java.lang.IllegalArgumentException: invalid value for field" in the log entry in the loadoldfile routine.

Even doing a oldvrec.spress= ovfile.readint(0) returns 641 instead of 70 (spress is the first field in the structure and is an integer). I have looked at this until I am blind, and I don't see the problem. Keep in mind that the old version still compiles, runs, reads, and writes just fine using the old structure. This "should" be a simple deal.

I'll entertain any ideas at this point. A .vdf file is attached so you can play with the old format file.

Thanks,

--- Jem

Missing Link Software
 

HotShoe

Well-Known Member
Licensed User
Longtime User
Of course. It fails in the loadoldfile routine at:

oldvrec= ovfile.ReadObject(0)

which is where it reads the record from disk. I have even tried to read the record one field at a time but that does not return the correct values. As stated above, something like:

oldvrec.spress= ovfile.ReadInt(0)

does not return the value stored in the file. I know this because I can still access those files by using the old version of the source and reading those files with the SAME typed record/structure.

Thanks,

--- Jem
 
Upvote 0

margret

Well-Known Member
Licensed User
Longtime User
I'm lost.. Is the old source and the new source running on the same device? Did the OS change?

I had this kind of thing happen to me not long ago with an SQL database. I updated from 2.2 to 2.3 and it would no longer load or access my SQL DB. It crashed each time. I then found a friend with the same device with the previous 2.2 still loaded and it works fine. I have yet to get that DB to work on the 2.3 with the same code.
 
Upvote 0

HotShoe

Well-Known Member
Licensed User
Longtime User
I'm lost.. Is the old source and the new source running on the same device? Did the OS change?
You and me both! No, nothing has changed on any of my devices (I use 5 of them to test with). All that has changed in regard to loading these files is the structure of those files in the new update. The old typed structure is untouched, and the new structure has several fields appended to the end, and 2 fields changed from Int to Double. Beyond that, nothing has changed in the way I read or write the files.

I am using the new structure to read new files, and the old structure to read old files. I even copied the old structure from a copy of the source (last version before changes) to make certain that I hadn't accidentally changed something. What baffles me is that it does read the new format with the new structure, but it refuses to read the old format files from the new version of the app.

I am reluctant to comment out all of the changes involving the new data structure because this is something of a major update and there are hundreds of occurrences in the app. Even if that somehow worked, it doesn't explain why I can read one or the other structure, but not both...

Thanks,

--- Jem
 
Upvote 0

HotShoe

Well-Known Member
Licensed User
Longtime User
Stack

Erel,

Here is the trace results:

(IllegalArgumentException) java.lang.IllegalArgumentException: invalid value for field
java.lang.reflect.Field.setField(Native Method)
java.lang.reflect.Field.set(Field.java:558)
anywheresoftware.b4a.randomaccessfile.RandomAccessFile.readType(RandomAccessFile.java:488)
anywheresoftware.b4a.randomaccessfile.RandomAccessFile.readObject(RandomAccessFile.java:464)
anywheresoftware.b4a.randomaccessfile.RandomAccessFile.readHelper(RandomAccessFile.java:388)
anywheresoftware.b4a.randomaccessfile.RandomAccessFile.ReadObject(RandomAccessFile.java:354)
com.mlsoft.VirtualDyno.main._loadoldfile(main.java:10231)
com.mlsoft.VirtualDyno.main._loadfile(main.java:10137)
com.mlsoft.VirtualDyno.main._dirlist_itemclick(main.java:6193)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:507)
anywheresoftware.b4a.BA.raiseEvent2(BA.java:113)
anywheresoftware.b4a.BA.raiseEvent2(BA.java:101)
anywheresoftware.b4a.objects.ListViewWrapper$1.onItemClick(ListViewWrapper.java:55)
android.widget.AdapterView.performItemClick(AdapterView.java:290)
android.widget.ListView.performItemClick(ListView.java:3599)
android.widget.AbsListView$PerformClick.run(AbsListView.java:1838)
android.os.Handler.handleCallback(Handler.java:587)
android.os.Handler.dispatchMessage(Handler.java:92)
android.os.Looper.loop(Looper.java:130)
android.app.ActivityThread.main(ActivityThread.java:3844)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:507)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
dalvik.system.NativeStart.main(Native Method)

Thanks.

--- Jem
 
Upvote 0

HotShoe

Well-Known Member
Licensed User
Longtime User
Erel,

Another quick note. I just renamed all members of the oldvdrecord type to see if there was a possible conflict since they are the same field names as the new record type. It had no effect on the exception though.

--- Jem
 
Upvote 0

HotShoe

Well-Known Member
Licensed User
Longtime User
Update

Erel,

After playing with the old version of the app which has worked flawlessly since it went on the market last July, I found an interesting twist. I found that if I renamed the original vdrecord typed structure to anything else, the app errors at the same point when it tries to load a vdrecord file from the device.

If I change the name back to the original name of vdrecord, it works fine again. Something in b4a is not being updated when a typed record's name is changed it seems.

I changed the new version of the app so that the original typed record is again named vdrecord, and the new type is now newvdrecord, and I can now read the old file formats.

Thought you should know about this. I use structures/records in most of my programs, but I may be one of the few doing so in b4a, I don't know.

Thanks,

--- Jem
 
Upvote 0

HotShoe

Well-Known Member
Licensed User
Longtime User
writeobject

Are you saying that the object name (vdrecord) is stored in the file that is created? I have just been through several of the files and don't find the object name in there. I just assumed that this was a simple blockread/blockwrite method.

Can you tell me where I can find the object name written so that I can change that and rename the typed object to make more sense in my source code?

Thanks,

--- Jem
 
Upvote 0

HotShoe

Well-Known Member
Licensed User
Longtime User
Ok, thanks, I'll do that from now on.

--- Jem
 
Upvote 0
Top