2.2. Opening Files
The simplest way to open a file is to pass a file name to the constructor of
either File_Database
or Readonly_Database
.
tutorial::File_Database db("file.joedb");
tutorial::Readonly_Database db("file.joedb");
2.2.1. joedb::Open_Mode
You can change the way the file is opened by passing an extra parameter to the
constructor of File_Database
. Available modes are:
enum class Open_Mode
{
read_existing, // mode of Readonly_Database
write_existing,
create_new,
write_existing_or_create_new, // default mode of File_Database
shared_write,
write_lock
};
shared_write
is dangerous, and requires synchronization. Users of the
library should not directly manipulate files with this mode, and instead use
transactions. Other write modes will use file locking to
prevent more than one process from writing to the same file simultaneously.
write_lock
is like write_existing_or_create_new
, but waits instead of
failing if anybody else is already write-locking.
For example:
#include "tutorial/File_Database.h"
#include "tutorial/Readonly_Database.h"
#include "joedb/io/main_exception_catcher.h"
/////////////////////////////////////////////////////////////////////////////
static int file_tutorial_main(int argc, char **argv)
/////////////////////////////////////////////////////////////////////////////
{
const char * const file_name = "file_tutorial.joedb";
//
// Create a new database and write something
// (If a file already exists, it will fail)
//
{
tutorial::File_Database db(file_name, joedb::Open_Mode::create_new);
db.new_city("Villeneuve d'Ascq");
db.checkpoint();
}
//
// Re-open the database and add one more city
// (If the file does not exist, it will fail)
//
{
tutorial::File_Database db(file_name, joedb::Open_Mode::write_existing);
db.new_city("Tombouctou");
db.checkpoint();
}
//
// Open the database read-only
//
{
tutorial::Readonly_Database db(file_name);
for (const auto city: db.get_city_table())
std::cout << db.get_name(city) << '\n';
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
/////////////////////////////////////////////////////////////////////////////
{
return joedb::main_exception_catcher(file_tutorial_main, argc, argv);
}
2.2.2. Generic_File_Database
Generic_File_Database
is a superclass of File_Database
that takes a
reference to a Generic_File
as parameter to its constructor, instead
of a file name. Subclasses of Generic_File
allows accessing data in
various ways:
Stream_File
uses astd::streambuf
.
Memory_File
writes to astd::vector<char>
in memory.
Readonly_Memory_File
reads fromconst char *
. joedb_embed can be used to embed a joedb database into a C++ string literal.
File_Slice
is a specialization ofReadonly_Memory_File
that reads a range of bytes from a Posix file by memory-mapping it. It can be used to read Android assets (Documentation).
File
is a typedef to eitherWindows_File
,Posix_File
, orPortable_File
. System-specific version ofFile
offer extra features, such as locking, which is necessary to handle concurrent access to a file.
SFTP_File
read-only access to a file via sftp (uses libssh).
CURL_File
read-only access to a file via any URL (uses libcurl).
Interpreted_File
can read joedbi commands directly.
Encoded_File
performs on-the-fly encoding and decoding of data. This can be used for transparent compression or encryption. Does not support concurrency and durability.
Upgradable_File<File_Type>
makes all write operations successful, but nothing is actually written to the file. This is convenient if you want to apply automatic schema upgrades to a read-only file.
You can also create your own file class by subclassing Generic_File
and
implementing its virtual functions.