iOS Question Using B4j Map in B4i

ilan

Expert
Licensed User
Longtime User
hi

i am working on a b4i app and i am making a tool in b4j to create maps easier

the problem is that the map is not read correct in b4i.

i am using hebrew letters and i think that the reason why its not working correct because english letters does work.

how should i do it so a b4j map will work also in b4i? should i convert string to byte and save a map with bytes and then read the bytes to string in b4i?

thanx, ilan
 
D

Deleted member 103

Guest
Hi ilan,

have you already tried the functions "ReadB4XObject" and "WriteB4XObject" from the library RandomAccessFile?
 
Upvote 0
D

Deleted member 103

Guest
i dont know this function. how can i use it with maps?

B4X:
Public Sub MapToString(mp As Map) As String
    Dim stu As StringUtils

    If File.Exists(File.DirTemp, "tmp.dat") Then
        File.Delete(File.DirTemp, "tmp.dat")
    End If
    
    Dim raf As RandomAccessFile
    raf.Initialize(File.DirTemp, "tmp.dat", False)
    raf.WriteB4XObject(mp, raf.CurrentPosition)
    raf.Close

    Dim buffer() As Byte = FileToBytes(File.DirTemp, "tmp.dat")
    Dim tmp As String = stu.EncodeBase64(buffer)
    Log("MapToString: tmp.Length= " & tmp.Length)
    
    Return tmp
End Sub

Public Sub MapFromString(Text As String) As Map
    Dim mp As Map
    Dim stu As StringUtils
    Dim buffer() As Byte = stu.DecodeBase64(Text)

    If File.Exists(File.DirTemp, "tmp.dat") Then
        File.Delete(File.DirTemp, "tmp.dat")
    End If
    
    BytesToFile(File.DirTemp, "tmp.dat", buffer)
    
    Dim raf As RandomAccessFile
    raf.Initialize(File.DirTemp, "tmp.dat", False)
    mp = raf.ReadB4XObject(raf.CurrentPosition)
    raf.Close

    Return mp
End Sub
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
B4X:
Public Sub MapToString(mp As Map) As String
    Dim stu As StringUtils

    If File.Exists(File.DirTemp, "tmp.dat") Then
        File.Delete(File.DirTemp, "tmp.dat")
    End If
   
    Dim raf As RandomAccessFile
    raf.Initialize(File.DirTemp, "tmp.dat", False)
    raf.WriteB4XObject(mp, raf.CurrentPosition)
    raf.Close

    Dim buffer() As Byte = FileToBytes(File.DirTemp, "tmp.dat")
    Dim tmp As String = stu.EncodeBase64(buffer)
    Log("MapToString: tmp.Length= " & tmp.Length)
   
    Return tmp
End Sub

Public Sub MapFromString(Text As String) As Map
    Dim mp As Map
    Dim stu As StringUtils
    Dim buffer() As Byte = stu.DecodeBase64(Text)

    If File.Exists(File.DirTemp, "tmp.dat") Then
        File.Delete(File.DirTemp, "tmp.dat")
    End If
   
    BytesToFile(File.DirTemp, "tmp.dat", buffer)
   
    Dim raf As RandomAccessFile
    raf.Initialize(File.DirTemp, "tmp.dat", False)
    mp = raf.ReadB4XObject(raf.CurrentPosition)
    raf.Close

    Return mp
End Sub

thank you @Filippo but is there maybe a simpler way?
i am trying to convert string to byte and put that as the value and then read it as byte and convert to string but i am getting an error:

Waiting for debugger to connect...
Program started.
professionMap.map
C:\ilan\Broken HD\F\B4I APPS IOS\speakinglish IN PROGRESS\stuff\mapCreator\Objects\
[B@4d98050a
Error occurred on line: 68 (Main)
java.lang.ClassCastException: java.lang.String cannot be cast to [Ljava.lang.String;
at b4j.example.main._updatetable(main.java:170)
at b4j.example.main._loadbtn_click(main.java:383)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:613)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:231)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:159)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:90)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:93)
at anywheresoftware.b4a.BA$1.run(BA.java:215)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
 
Upvote 0
D

Deleted member 103

Guest
thank you @Filippo but is there maybe a simpler way?
I'm sorry, the code sample is from one of my app.
Try this code, it's a lot easier. :)
B4X:
Sub SaveMap(mp As Map)
    Dim raf As RandomAccessFile
    raf.Initialize2(File.DirTemp, "tmp.dat", False)
    raf.WriteB4XObject(mp, raf.CurrentPosition)
    raf.Close       
End Sub

Sub ReadMap As Map
    Dim mp As Map
    Dim raf As RandomAccessFile
    raf.Initialize(File.DirTemp, "tmp.dat", False)
    mp = raf.ReadB4XObject(raf.CurrentPosition)
    raf.Close
    Return mp
End Sub
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
If you don't want to save the data to a file then you can use B4XSerializator.

Thanx erel but i need to get the maps i create in b4j to my b4i project. So i guess i need to save it to a file or i create a big module that creates all maps on app start.

What would u recommend?
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
thanx a lot @Filippo, your code works great.

i had to change very small parts in it

1. in b4j the .Initialize2 of randomaccessfile expect 4 parameters so i added to the last also False.

2. in b4i i could not read the file from Asset.Folder so i change the ReadOnly value of the initialize of RandomAccessFile lib

B4X:
Sub SaveMap(mapName As String, mp As Map) 'ignore
    If mp.Size = 0 Then Return
    Dim raf As RandomAccessFile
    raf.Initialize2(File.DirDocuments, mapName & ".map", False, False)
    raf.WriteB4XObject(mp, raf.CurrentPosition)
    raf.Close
End Sub

Sub ReadMap(path As String, mapN As String) As Map
    Dim mp As Map
    Dim raf As RandomAccessFile
    raf.Initialize(path, mapN, True)
    mp = raf.ReadB4XObject(raf.CurrentPosition)
    raf.Close
    Return mp
End Sub

and now i can read hebrew letters with nikud and it works great.
b4x is really awesome a simple. :)
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
You can choose which endianess that you like. Just make sure to use the same one in all cases.

As I wrote, I would have used B4XSerializator instead as it doesn't require random access.

B4X:
Dim ser As B4XSerializator
BytesToFile(..., set.ObjectToBytes(mp))
'read
Dim mp As Map = ser.BytesToObject(FileToBytes(...))
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
Ok erel thank you i will try it when i get home.

So just to understand b4xserializator can i write any object to byte and read it back?

Also list of objects like type object?

Thanx, ilan
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
hi @Erel i have tried your solution but i am getting an error.

Application_Start
Error occurred on line: 329 (Main)
Error opening stream: Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory" UserInfo={_kCFStreamErrorCodeKey=2, _kCFStreamErrorDomainKey=1}
Stack Trace: (
CoreFoundation __exceptionPreprocess + 171
libobjc.A.dylib objc_exception_throw + 48
CoreFoundation +[NSException raise:format:] + 197
result -[B4IFile OpenInput::] + 418
result -[b4i_main _filetobytes::] + 844
result -[b4i_main _readmap::] + 872
result -[b4i_main _initializemaps] + 789
result -[b4i_main _application_start:] + 4753
CoreFoundation __invoking___ + 140
CoreFoundation -[NSInvocation invoke] + 320
result +[B4I runDynamicMethod:method:throwErrorIfMissing:args:] + 1645
result -[B4IShell runMethod:] + 412
result -[B4IShell raiseEventImpl:method:args::] + 2487
result -[B4IShellBI raiseEvent:event:params:] + 1450
result __33-[B4I raiseUIEvent:event:params:]_block_invoke + 50
libdispatch.dylib _dispatch_call_block_and_release + 12
libdispatch.dylib _dispatch_client_callout + 8
libdispatch.dylib _dispatch_main_queue_callback_4CF + 1260
CoreFoundation __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
CoreFoundation __CFRunLoopRun + 2402
CoreFoundation CFRunLoopRunSpecific + 409
GraphicsServices GSEventRunModal + 62
UIKit UIApplicationMain + 159
result main + 111
libdyld.dylib start + 1
)
Application_Active

reading the same file via b4j doe work but with b4i i am getting an error.
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
and sometimes i get this error:

Copying updated assets files (53)
:(null),0
Error opening stream: Error Domain=NSPOSIXErrorDomain Code=17 "File exists" UserInfo={_kCFStreamErrorCodeKey=17, _kCFStreamErrorDomainKey=1}
Stack Trace: (
CoreFoundation __exceptionPreprocess + 171
libobjc.A.dylib objc_exception_throw + 48
CoreFoundation +[NSException raise:format:] + 197
result -[B4IFile OpenOutput:::] + 481
result -[B4IShell virtualAssets] + 1303
result -[B4IShell start:] + 164
result -[B4IShellBI raiseEvent:event:params:] + 203
result __33-[B4I raiseUIEvent:event:params:]_block_invoke + 50
libdispatch.dylib _dispatch_call_block_and_release + 12
libdispatch.dylib _dispatch_client_callout + 8
libdispatch.dylib _dispatch_main_queue_callback_4CF + 1260
CoreFoundation __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
CoreFoundation __CFRunLoopRun + 2402
CoreFoundation CFRunLoopRunSpecific + 409
GraphicsServices GSEventRunModal + 62
UIKit UIApplicationMain + 159
result main + 111
libdyld.dylib start + 1
)
SignalHandler 6
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
this is my code:

b4j:

B4X:
Sub SaveMap(mp As Map) 'ignore
    If mp.Size = 0 Then Return
    Dim ser As B4XSerializator
    BytesToFile(File.DirApp, mapName.Text & ".map",ser.ConvertObjectToBytes(mp))
End Sub

Sub ReadMap(path As String, mapN As String) As Map
    Dim ser As B4XSerializator
    Dim mp As Map = ser.ConvertBytesToObject(FileToBytes(path,mapN))
    Return mp
End Sub

Sub BytesToFile (Dir As String, FileName As String, Data() As Byte)
    Dim out As OutputStream = File.OpenOutput(Dir, FileName, False)
    out.WriteBytes(Data, 0, Data.Length)
    out.Close
End Sub

Sub FileToBytes (Dir As String, FileName As String) As Byte()
    Return Bit.InputStreamToBytes(File.OpenInput(Dir, FileName))
End Sub

b4i:

B4X:
Sub SaveMap(mapName As String, mp As Map) 'ignore
    If mp.Size = 0 Then Return
    Dim ser As B4XSerializator
    BytesToFile(File.DirDocuments,mapName & ".map",ser.ConvertObjectToBytes(mp))
End Sub

Sub ReadMap(path As String, mapN As String) As Map
    Dim ser As B4XSerializator
    Dim mp As Map = ser.ConvertBytesToObject(FileToBytes(path,mapN))
    Return mp
End Sub
'
Sub BytesToFile (Dir As String, FileName As String, Data() As Byte)
    Dim out As OutputStream = File.OpenOutput(Dir, FileName, False)
    out.WriteBytes(Data, 0, Data.Length)
    out.Close
End Sub

Sub FileToBytes (Dir As String, FileName As String) As Byte()
    Return Bit.InputStreamToBytes(File.OpenInput(Dir, FileName))
End Sub

read in b4i:

B4X:
    proffesionMap.Initialize
    proffesionMap = ReadMap(File.DirAssets,"proffesionMap.map")
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
ok, i found the reason for that error. it seems like B4I failed to copy my map files to the local server because of the file extension ".map"

after changing the extension to another string it worked. b4j has no problem handling *.map files.
 
Upvote 0
Top