Reading and Writing Data
IXFile is data-oriented component that provides functionality for reading and writing data of commonly used types: individual bits,
integral and floating point numbers, ANSI and Unicode texts in several formats, variants and binary structures.
With GetBit, GetByte, GetShort,
GetLong, GetFloat, GetDouble,
GetText, GetUnicodeText, GetVariant,
GetBinary and PutBit, PutByte,
PutShort, PutLong, PutFloat,
PutDouble, PutText, PutUnicodeText,
PutVariant, PutBinary methods, you can simply and easily read and write data
sequence of specified length. File position can also be specified to automatically set active file position to access data at; by default current position
is used. When operation completes, file position is advanced by the number of bytes actually read or written, thus allowing sequential access without specifying
next position; see Positioning File for more information. All Get methods return the number of elements (not bytes)
actually read, which may be less than expected if end of the file is encountered prematurely. Only complete elements can be read; if there is not enough data
in file for next full element processing is finished and file remains positioned after last complete element. C++ developers also have GetAlloc versions of methods
that can allocate buffer of appropriate size for read data and return it to the user. In addition, GetBlock method is available for direct
access to internal data buffer. Data is saved to file automatically whenever internal buffer is full of written data, file is repositioned, resized, closed or detached.
Bit buffer is also written even if it does not contain complete byte; in such case it is left padded with zero bits to fill entire byte. You can always call
Flush method to force writing data to file.
Individual bits are buffered in special bit buffer which is one byte long and contains at most 8 bits to be accessed one by one. Bits are fetched from right to left,
starting from least significant bit. If user requests more bits that are available in buffer, it is refilled with one complete byte read from file and file
positon is moved forward by one byte. Such behaviour guarantees that other non-bit data read by user is always accessed on byte boundary regardless of
number of bits present in bit buffer. Read and written bits are never mixed in buffer; if GetBit call is followed by PutBit, bit buffer is discarded
before bits are written; if PutBit call is followed by GetBit, bit buffer is written to file before bits are read.
Text data is supported with both ANSI and Unicode character encoding and several formats. IXFile represents text as length-prefixed by default;
actual text data in file is preceeded with a long number specifying length of the text in characters which is read or written first and then exact number of
characters. NULL- and CR/LF terminated texts are also supported to allow simple access to usual text files. In addition raw text format allows processing
of arbitrary strings without regard to any termination or prefix. Please note that methods for reading text return number of characters returned to the user
and not the number of characters read from file; if text is formatted as length-prefixed or NULL- or CRLF-terminated, entire text is always read from file even
if smaller number of characters is returned to user.
IXFile also supports structured data containing fields of various types. With GetBinary and PutBinary
methods, you can read and write binary block of data which can represent arbitrary data structure. In such case entire structure should be treated as a sequence of bytes whose
length is equal to total size of the structure. File data must be, however, in machine (little-endian) byte order because there is no way to determine structure of data and types of fields
for big-endian conversion. Methods can also be used for accessing data of simple types that are not directly supported like Boolean, Date, Currency or Decimal;
in such case size of elements must be specified to properly handle big-endian conversion.
Visual Basic developers would preferably use GetVariant and PutVariant methods
for the purpose of accessing structured data. Big advantage of these methods relies on known structure of data; each data field is of known type and therefore can be correctly handled by IXFile,
relieving developers of technical details of data storage. Accessed variant can be a single variable or one dimensional array (possibly with nested subarrays) of one of allowed types:
Byte, Integer, Long, Single, Double, String, Boolean, Date, Currency, Decimal and Variant.
With such possibilities you can read and write really complex data; the only limitation is that all arrays must be one dimensional. Text in variant is always represented
by IXFile as length-prefixed Unicode string and therefore it is not possible to read structures with raw or terminated texts. Methods also allow to specify number of elements of variant
that constitute data sequence; by default all elements are used but you can specify that only some initial fields should be recognized. Please note, however, that number of elements
always specifies total number of elements in data sequence regardless of its structure; in other words if variant consists of nested subarrays, it specifies number of
elements counted recursively through all subarrays and not elements in most outer array.
All data transferred with IXFile is buffered internally to optimize performance; size of buffer is determined when Initialize is called and cannot be changed.
In some situations, however, it may be necessary to change amount of buffered data, especially for performance reasons. For such purposes active buffer size is
defined which determines what part of data buffer is used in read and write operations; in other words it specifies how much file data is buffered.
With SetActiveBufferSize method, developers can optimize application performance by adaptively changing size of active buffer.
Unbuffered transfer is also possible by setting active buffer size to 0; in such case internal data buffer always stays empty and no data is read ahead nor buffered before writing.
Active buffer size is reset to its default value whenever new file is opened or attached to the object, so it should be changed after opening or attaching file.
To check how much data is currently in internal buffer GetBlockSize should be called. To verify number of bytes transferred during last operation,
GetTransfer should be called; please note that method returns number of bytes transferred with last Get or Put operation only.
In addition, GetReadTransfer and GetWriteTransfer can be called to obtain total number of bytes transferred
during all Get and Put operations.
int main(int, char**)
long rtran, wtran, tran, size;
ixf.Open("test.bin", TRUE, TRUE);
data.bits = 0xF1;
data.shrt = 0x0101;
data.shrt = 0x0202;
data.shrt = 0x0303;
data.dbl = 1.23456789;
data.dbl = -9.87654321;
strcpy(data.txt,"This is a test");
ixf.PutBit(data.bits, 5, 10);
ixf.PutBinary(&data.dec, 1, sizeof(DECIMAL));
ixf.PutText(data.txt, 256, -1, IXF_TEXT_STRING);
wtran = ixf.GetWriteTransfer();
size = ixf.GetSize();
rtran = ixf.GetReadTransfer();
tran = ixf.GetTransfer();
Dim ixf As IXFile
Dim data(4) As Variant
Dim bits As Byte
Dim shrt(2) As Integer
Dim dbl(1) As Double
Dim dec As Variant
Dim txt As String
Dim rtran As Long, wtran As Long, tran As Long, size As Long
Set ixf = New IXFile
ixf.Open "test.bin", True, True
bits = &HF1
shrt(0) = &H0101
shrt(1) = &H0202
shrt(2) = &H0303
dbl(0) = 1.23456789
dbl(1) = -9.87654321
dec = CDec(123456789.87654321)
txt = "This is a test"
data(0) = bits
data(1) = shrt
data(2) = dbl
data(3) = dec
data(4) = txt
ixf.PutBit data(0), 5, 10
wtran = ixf.GetWriteTransfer
size = ixf.GetSize
ixf.GetVariant data, -1, 10
rtran = ixf.GetReadTransfer
tran = ixf.GetTransfer
Set ixf = Nothing