save file, reboot, now size 0

wheretheidivides

Active Member
Licensed User
Longtime User
I have a program that saves a variable to disk (CurrentDB). This allow a user to enter a name for a database. This creates folders and such. The variable is saved onto SD card. Restarting the program is fine. However, if I turn off the phone and restart, then the file is sometimes messed up. There won't be any text in the file and the filesize will be 0. Sometimes it will be OK though with text.

Here are the important code. The point at which it crashes is in the sub 'INIloadCurrentDB' on line 'ListCDB = File.ReadList(File.DirRootExternal, "/Saved/PDTK/CurrentDB.txt")'. So looking at the code is it as simple as an incorrect code format or is there something else going on? Do you have to close out the file somehow when you exit the program so it saves the info? (Forgive me, I'm not that good of a programmer)

B4X:
Sub Activity_Resume
   CurrentDB = "Default" 'start as default and then rename it
   If File.Exists (File.DirRootExternal, "/Saved/PDTK/CurrentDB.txt") Then
      INIloadCurrentDB 'SR
      CreateFileFolders 'SR
      CreateFilePaths 'SR
   Else
      FTsetup 'SR      
      CreateFileFolders 'SR
      CreateFilePaths 'SR   
      INIsaveCurrentDB 'SR
   End If
end sub

Sub INIsaveCurrentDB
'-----------------------------------------------
   If CurrentDB = "" Then
      CurrentDB = "Default"
   End If
'-----------------------------------------------
'Save location to text file on SD card
   Dim ListCDB As List
       ListCDB.Initialize
      ListCDB.Add(CurrentDB) '0
   '---------------------------------------
      'leave absolution Address
   File.WriteList(File.DirRootExternal & "/Saved/PDTK/", "CurrentDB.txt", ListCDB)
   '---------------------------------------
   Label1121L.Text = "DB: " & CurrentDB
'-----------------------------------------------
End Sub

Sub INIloadCurrentDB
'---------------------------------------------
'Loads location from text file on SD card and puts into variable
   If File.Exists (File.DirRootExternal, "/Saved/PDTK/CurrentDB.txt") Then
      Dim ListCDB As List
      'leave absolute address
      ListCDB = File.ReadList(File.DirRootExternal, "/Saved/PDTK/CurrentDB.txt")
      CurrentDB = ListCDB.Get(0)
   Else
      CurrentDB = "Default"
   End If
   '---------------------------------------
   If CurrentDB = "" Then
      CurrentDB = "Default"
   End If
   '---------------------------------------
   Label1121L.Text = "DB: " & CurrentDB
'-----------------------------------------------
End Sub
Sub CreateFileFolders
'-----------------------------------------
   If File.Exists(File.DirRootExternal, "/Saved") = False Then
        File.MakeDir (File.DirRootExternal, "/Saved")
   End If
   '-------------------------------------------------------------------------
   If File.Exists(File.DirRootExternal, "/Saved/PDTK") = False Then
        File.MakeDir (File.DirRootExternal, "/Saved/PDTK")
   End If
end sub

Sub CreateFilePaths
'-------------------------------------------------------------------------
'Settings (Txt)
   fpCDB = "/Saved/PDTK/CurrentDB.txt"
end sub
 

margret

Well-Known Member
Licensed User
Longtime User
I would let the user enter a file name only to create the file. To load a file they should select it from a list that is built and stored when they create a new file. In Activity pause, you should be saving the current file name last in use. I would also make the variable that holds the file name a process global.

Your other code jumps to other subs that makes it hard to tell what is going on without seeing the complete project. I don't see an Activity resume.
 
Upvote 0

wheretheidivides

Active Member
Licensed User
Longtime User
I would let the user enter a file name only to create the file. (I do. the first time run)

To load a file they should select it from a list that is built and stored when they create a new file(I do in one of the panels I have a db load so they can change dbs. haven't made it yet though until this works)

In Activity pause, you should be saving the current file name last in use. (I do)
Sub Activity_Pause (UserClosed As Boolean)

INIsaveCurrentDB 'SR

'-----------------------------------------------
End Sub
I would also make the variable that holds the file name a process global ( do).

Your other code jumps to other subs that makes it hard to tell what is going on without seeing the complete project. I don't see an Activity resume (listed below).

B4X:
Sub Activity_Resume
'-----------------------------------------------
   'InitializeCamera 'SR
'-----------------------------------------------
'set 4 digit year and create a folder with that year to save pics into (Expenses)
   DateTime.DateFormat = "yyyy"
   dt2 = DateTime.Date(DateTime.now)
   TodayDate 'SR
'---------------------------------------------
'Load CurrentDB
   CurrentDB = "Default" 'start as default and then rename it
   If File.Exists (File.DirRootExternal, "/Saved/PDTK/CurrentDB.txt") Then
      INIloadCurrentDB 'SR
      CreateFileFolders 'SR
      CreateFilePaths 'SR
   Else
      FTsetup 'SR      
      CreateFileFolders 'SR
      CreateFilePaths 'SR   
      INIsaveCurrentDB 'SR
   End If
   
   Label1121L.Text = "DB: " & CurrentDB
'------------------------------------
   INIloadWhichLocation 'SR
   INIloadSettings 'SR
   INIloadString 'SR
   INIloadGlobalEventID 'SR
   INIloadGlobalTransID 'SR
   INIloadLastDateConverted 'SR

'=========================================================================
'reset pointers of work areas, if db exists, then load all fields.  if doesnt exists, then create work area structure
   db.ResetPointers
   '-----------------------------------------------------------
   If db.Exist(File.DirRootExternal & FPdbDataFolder) Then
      Selectdb5
      db.SelectWorkArea(5)
      db.GetRecord 'Gets all fields of 1 record and puts into variables
   Else
      Selectdb5 'Folder name for databases
   End If
   '-----------------------------------------------------------
   If db.Exist(File.DirRootExternal & FPdbCatForExp) Then
      Selectdb4
      db.SelectWorkArea(4) 
      db.GetRecord 'Gets all fields of 1 record and puts into variables
   Else
      Selectdb4 'SR work area 4-Cat for Expenses
   End If
   
   '---------------------------------------
   If db.Exist(File.DirRootExternal & FPdbEventID) Then
      Selectdb3
      db.SelectWorkArea(3) 
      db.GetRecord 'Gets all fields of 1 record and puts into variables
   Else
      Selectdb3 'SR work area 3 - Current Event ID
   End If
   
   '---------------------------------------
   If db.Exist(File.DirRootExternal & FPdbStringTr) Then
      Selectdb2
      db.SelectWorkArea(2)
      db.GetRecord 'Gets all fields of 1 record and puts into variables
   Else
      Selectdb2 'SR work area 2 - String Tracker
   End If
   
   '---------------------------------------
   If db.Exist(File.DirRootExternal & FPdbExpenses) Then
      Selectdb1
      db.SelectWorkArea(1)
      db.GetRecord 'Gets all fields of 1 record and puts into variables
   Else
      Selectdb1 'SR work area 1 - Expenses
   End If

   '---------------------------------------   
   If db.Exist(File.DirRootExternal & FPdbIncome) Then
      Selectdb0
      db.SelectWorkArea(0)
      db.GetRecord 'Gets all fields of 1 record and puts into variables
   Else
      Selectdb0 'SR work area 0 - Income
   End If

'-----------------------------------------------
End Sub
 
Upvote 0

margret

Well-Known Member
Licensed User
Longtime User
In the Resume sub below, the db.ResetPointers should be the very last command issued before End Sub. It will not work until the DataBases have been reopened. Look at the very end of this block of code and see the changes and comments I made.


B4X:
Sub Activity_Resume
'-----------------------------------------------
   'InitializeCamera 'SR
'-----------------------------------------------
'set 4 digit year and create a folder with that year to save pics into (Expenses)
   DateTime.DateFormat = "yyyy"
   dt2 = DateTime.Date(DateTime.now)
   TodayDate 'SR
'---------------------------------------------
'Load CurrentDB
   CurrentDB = "Default" 'start as default and then rename it
   If File.Exists (File.DirRootExternal, "/Saved/PDTK/CurrentDB.txt") Then
      INIloadCurrentDB 'SR
      CreateFileFolders 'SR
      CreateFilePaths 'SR
   Else
      FTsetup 'SR      
      CreateFileFolders 'SR
      CreateFilePaths 'SR   
      INIsaveCurrentDB 'SR
   End If
   
   Label1121L.Text = "DB: " & CurrentDB
'------------------------------------
   INIloadWhichLocation 'SR
   INIloadSettings 'SR
   INIloadString 'SR
   INIloadGlobalEventID 'SR
   INIloadGlobalTransID 'SR
   INIloadLastDateConverted 'SR

'=========================================================================
'reset pointers of work areas, if db exists, then load all fields.  if doesnt exists, then create work area structure
   
    '************************************************
    'db.ResetPointers -> Moved to the end of this sub.
   '-----------------------------------------------------------
   If db.Exist(File.DirRootExternal & FPdbDataFolder) Then
      Selectdb5
      db.SelectWorkArea(5)
      db.GetRecord 'Gets all fields of 1 record and puts into variables
   Else
      Selectdb5 'Folder name for databases
   End If
   '-----------------------------------------------------------
   If db.Exist(File.DirRootExternal & FPdbCatForExp) Then
      Selectdb4
      db.SelectWorkArea(4) 
      db.GetRecord 'Gets all fields of 1 record and puts into variables
   Else
      Selectdb4 'SR work area 4-Cat for Expenses
   End If
   
   '---------------------------------------
   If db.Exist(File.DirRootExternal & FPdbEventID) Then
      Selectdb3
      db.SelectWorkArea(3) 
      db.GetRecord 'Gets all fields of 1 record and puts into variables
   Else
      Selectdb3 'SR work area 3 - Current Event ID
   End If
   
   '---------------------------------------
   If db.Exist(File.DirRootExternal & FPdbStringTr) Then
      Selectdb2
      db.SelectWorkArea(2)
      db.GetRecord 'Gets all fields of 1 record and puts into variables
   Else
      Selectdb2 'SR work area 2 - String Tracker
   End If
   
   '---------------------------------------
   If db.Exist(File.DirRootExternal & FPdbExpenses) Then
      Selectdb1
      db.SelectWorkArea(1)
      db.GetRecord 'Gets all fields of 1 record and puts into variables
   Else
      Selectdb1 'SR work area 1 - Expenses
   End If


      '************ New Changes
      'Also these blocks can be changed like:
      If db.Exist(File.DirRootExternal & FPdbIncome) Then
            Selectdb0 'SR work area 0 - Income
            'db.SelectWorkArea(0) <- This is not needed
            If db.RecordCount > 0 Then db.GetRecord 'Gets all fields of 1 record and puts into variables
      End If
      db.ResetPointers 'This must be here after the DBs are opened.
'-----------------------------------------------
End Sub
 
Last edited:
Upvote 0

wheretheidivides

Active Member
Licensed User
Longtime User
thanks marget. I'll makes those changes and see if I can finally get this thing done.

I realized that I don't need to load those records because you have to select a button to enter each record area. So currently I have this. If there is a reason I shouldn't do it like this let me know. Just note the selectdb0 parts and the resetpointer part. This is a edited version but could always post more. This s is my first database experience ever.

Now I think I have the Database stuff working OK. It seems fine as I have tested it out. Now back to the topic of this thread. Sometimes when I load the variable back in, it gives a size 0. The info is on the first message. It doesn't do it every time I reboot though. When it does, I do have a 'default' set up then force the user to select his old database again. Annoying. So anyone have any ideas there?


B4X:
Sub Activity_Create(FirstTime As Boolean) 
'Load CurrentDB
   CurrentDB = "Default" 'start as default and then rename it
   '-----------------------------------
   'leave absolution filepath
   If File.Exists (File.DirRootExternal, "/Saved/PDTK/CurrentDB.txt") = True Then
      INIloadCurrentDB 'SR
      '-----
      If CurrentDB = "Default" Then
         'do not create folders for default
      Else
         CreateFileFolders 'SR
      End If
      '-----
      CreateFilePaths 'SR
      DB1T = False
   Else
      FTsetup 'SR
      '-----
      If CurrentDB = "Default" Then
         'do not create folders for default
      Else
         CreateFileFolders 'SR
      End If
      '-----
      CreateFilePaths 'SR
      INIsaveCurrentDB 'SR must come after folder setup
      DB1T = True
   End If
   
   Label1121L.Text = "DB: " & CurrentDB
'Set up DB structures
   Selectdb0
   Selectdb1
   Selectdb2
   Selectdb3
   Selectdb4
   Selectdb5
end sub
Sub Activity_Resume

'---------------------------------------------
'Load CurrentDB
   CurrentDB = "Default" 'start as default and then rename it
   
   If File.Exists (File.DirRootExternal, "/Saved/PDTK/CurrentDB.txt") = True Then
      INIloadCurrentDB 'SR
      '-----
      If CurrentDB = "Default" Then
         'do not create folders for default
      Else
         CreateFileFolders 'SR
      End If
      '-----
      CreateFilePaths 'SR
      DB1T = False
   Else
      FTsetup 'SR in case user deleted folders off of SD card
      '-----
      If CurrentDB = "Default" Then
         'do not create folders for default
      Else
         CreateFileFolders 'SR
      End If
      '-----
      CreateFilePaths 'SR
      INIsaveCurrentDB 'SR must come after folder setup
      DB1T = True
   End If
      
'------------------------------------
   INIloadWhichLocation 'SR
   INIloadSettings 'SR
   INIloadString 'SR
   INIloadGlobalEventID 'SR
   INIloadGlobalTransID 'SR
   INIloadLastDateConverted 'SR

'=========================================================================
'Set up DB structures
   Selectdb0
   Selectdb1
   Selectdb2
   Selectdb3
   Selectdb4
   Selectdb5
   
   db.ResetPointers
   
'--------------------------------------
'if first time then add record to db.  must go here after files and structure are set up
   If DB1T = True Then
      'db.SelectWorkArea(5)
      PutAllFields_5 'SR
      db.AddRecord 'dont do in ftsetup as there are no file paths setup yet
   Else
      'nothing
   End If

end sub
 
Last edited:
Upvote 0

margret

Well-Known Member
Licensed User
Longtime User
The variable should be a process global, you should check it is not empty before you save it. It should be the first thing you save to disk in the Activity_Pause. That way it should always have a value in it. In activity_resume, check for the existence of the file that is saved and if not found, force them at that point to select a DataBase to work with.

A better way would be to do this each time they select a DataBase to work with, write the file name and path to the file right then and do not do it in Activity_pause. That way it will always be populated with the last file they were using. Then read this file in Activity_Resume and the app will not be trying to save this info during the Activity_pause.
 
Upvote 0

wheretheidivides

Active Member
Licensed User
Longtime User
The variable should be a process global, you should check it is not empty before you save it. It should be the first thing you save to disk in the Activity_Pause. That way it should always have a value in it. In activity_resume, check for the existence of the file that is saved and if not found, force them at that point to select a DataBase to work with.

A better way would be to do this each time they select a DataBase to work with, write the file name and path to the file right then and do not do it in Activity_pause. That way it will always be populated with the last file they were using. Then read this file in Activity_Resume and the app will not be trying to save this info during the Activity_pause.

Yeah I did all of that. There's something weird going on when I save stuff (not related to databases).
 
Last edited:
Upvote 0
Top