Store user data in one file - how?

Everything else that doesn't fall into one of the other PB categories.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Store user data in one file - how?

Post by PB »

Hi all,

My flagship app stores a lot of dynamic user information. Sometimes it's just
one line of text, and other times it's many lines. Currently I store all these as
single plain text files on disk, mainly because I wanted to be able to delete
and edit them manually without running the app. The data stored is always
just plain text like names, file paths, and so on. No binary data.

But now I think I'd prefer to store it all in one local file, to make it portable.
How the heck do I convert all my code to do that? I know nothing about
databases so using MySQL (and such) is a no-no due to lack of time to
learn it.

Do you think using a single INI file with groups is what I should do? From
what I can see from the manual, it looks doable and allows me to store
and delete data dynamically from it. Should I try writing procedures that
emulate the CreateFile and ReadFile commands but that works on an INI
file instead? I think that would make the conversion go quicker than doing
it all from scratch?

Any ideas appreciated. Thanks.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

If you wish to retain the ability to manually edit these files then yes a PB preferences file or some kind of CSV file or an XML file would seem logical choices. Even consider using an Excel spreadsheet which you can access either via COMatePLUS or through PB's database library (via ODBC).

Personally, I would consider using an SQLite database. Not directly editable of course; but very convenient and very easy to learn how to use. Would take you about 10 minutes to get to grips with it. :)
I may look like a mule, but I'm not a complete ass.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

What about a .ini file?
Look under "preference" in the PB help. I think that should be easy to use, here is an example on how I used it in a application:

Code: Select all

OpenPreferences("config.ini")
  PreferenceGroup("GetCategories")
   GetCategory\Unknown     = ReadPreferenceLong("Unknown",1)
   GetCategory\Business    = ReadPreferenceLong("Business",1)
   GetCategory\Cable       = ReadPreferenceLong("Cable",1)
   GetCategory\Children    = ReadPreferenceLong("Children",1)
   GetCategory\Documentary = ReadPreferenceLong("Documentary",1)
   ;...
  
  PreferenceGroup("Misc")
   Settings\RememberWindow = ReadPreferenceLong("RememberWindowSize",1)
   Settings\RememberColumn = ReadPreferenceLong("RememberColumnWidth",1)
   Settings\RememberCountry = ReadPreferenceLong("RememberCountry",1)
   SelectedCountry = ReadPreferenceLong("LastCountry",1)
  
  PreferenceGroup("Column widths")
   Column1Width    = ReadPreferenceLong("Column1",80)
   Column2Width    = ReadPreferenceLong("Column2",70)
   Column3Width    = ReadPreferenceLong("Column3",44)
   Column4Width    = ReadPreferenceLong("Column4",42)
   Column5Width    = ReadPreferenceLong("Column5",180)
ClosePreferences()
Edit: Oh, I see you just edited your post, hehe... (well, at least I didn't notice the part about .ini before)
Last edited by Joakim Christiansen on Fri Jul 31, 2009 1:47 pm, edited 1 time in total.
I like logic, hence I dislike humans but love computers.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

Not edited. :)

Anyway, what about multiple lines when using INI files? I don't think the
preferences lib supports that?
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Anyway, what about multiple lines when using INI files? I don't think the preferences lib supports that?
Depends on what you mean? If you mean that individual strings may contain EOL characters in order to separate multiple lines of text etc. then you are correct. You would need to add some kind of encoding yourself. Then again this is true for all text based files. I generally save in utf-8 format when doing this but prefix each string with 4 bytes giving the number of bytes in the string. I then use ReadData() to retrieve the string etc. This of course is heading towards some kind of binary file which may not suit your purposes on this occasion.

xml has no problem with multiple lines for each node's text.
I may look like a mule, but I'm not a complete ass.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

I mean my data will have #CRLF$ in it, so using the preferences lib won't be
able to handle that, because it's one line per item entry. I really don't want
to have to learn MySQL. I'll probably just drop the idea. The app is still
portable anyway -- just copy the folder and not the individual files. ;)
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

As I say; there is always XML.
I may look like a mule, but I'm not a complete ass.
User avatar
utopiomania
Addict
Addict
Posts: 1655
Joined: Tue May 10, 2005 10:00 pm
Location: Norway

Post by utopiomania »

I use PB preference files, which can easily be edited in Notepad if you need to:

Code: Select all

procedure writePreferences(inFolder.s, name.s)
  #CSIDL_APPDATA = $1A
  ;	XP:     C:\Documents and Settings\username\Application Data*    
  ;	Vista:  C:\Users\username\AppData\Roaming
  if len(inFolder)
    inFolder + "\"
  endIf
  path.s = getPathPart(programFileName())
  type = getDriveType_(left(path, 2))
  if type = 2
    ;removable
    path = path + inFolder
  else
    path = getSpecialFolder(#CSIDL_APPDATA) + inFolder
  endIf
  createDirectory(path)
  if createPreferences(path + name)
    writePreferenceLong("language", lang)
    writePreferenceString("fileExtensions", fileExt)
    writePreferenceLong("deleteFiles", delFiles)
    writePreferenceLong("allUsers", allUsers)
    writePreferenceLong("yearFolder", yearFolder)
    writePreferenceLong("dateFolder", dateFolder)
    closePreferences()
    procedureReturn 1    
  endIf
  procedureReturn 0
endProcedure

procedure readPreferences(inFolder.s, name.s)
  #CSIDL_APPDATA = $1A
  ;	XP:     C:\Documents and Settings\username\Application Data*    
  ;	Vista:  C:\Users\username\AppData\Roaming
  if len(inFolder)
    inFolder + "\"
  endIf
  path.s = getPathPart(programFileName())
  type = getDriveType_(left(path, 2))
  if type = 2
    ;removable
    path = path + inFolder + name
  else
    path = getSpecialFolder(#CSIDL_APPDATA) + inFolder + name
  endIf
  openPreferences(path)
  lang = readPreferenceLong("language", 0)
  tempLang = lang
  fileExt = readPreferenceString("fileExtensions", defaultFileExt)
  delFiles = readPreferenceLong("deleteFiles", 0)
  allUsers = readPreferenceLong("allUsers", 1)
  yearFolder = readPreferenceLong("yearFolder", 1)
  dateFolder = readPreferenceLong("dateFolder", 0)
  closePreferences()
endProcedure
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Post by Edwin Knoppert »

Two tips:

1) IStorage interface

2) Sqlite
Post Reply