Page 1
Page 2
Introduction
File access in eVB is typically done
with the File control. Unfortunately, the control has distinct
limitations when binary or ASCII files need to be handled,
plus the File control takes up more resources and is slower
than using the API.
I recently did some perusing through
just about every eVB online resource I could think of, and
couldn't find any good examples of using the CreateFile,
WriteFile and ReadFile APIs. In fact, the only working example
I could find iterated through the data buffer and either
read or wrote a single byte at a time. While functional,
this is significantly slower than just reading or writing
an entire block of data at once.
Since I couldn't find a sample I liked,
I decided to once again put my own grey matter to work and
write a sample application.
Background Info
While using the API to manipulate files
is relatively straightforward, there are a few things that
you need to know before getting started.
First, Windows CE uses Unicode strings
and PCs use ANSI strings. The reason for Unicode is that
ANSI cannot handle the languages that have more than 255
possible characters. What it means to you as a developer
is that all CE Strings are 2 bytes per character instead
of one.
This is important to keep in mind when
handling the files, but also if you have to transfer the
file. By simply changing a file from Unicode to ANSI, you
cut it's size in half, and if you are using an ANSI compatible
language you lose nothing in the process.
Secondly you need to understand how
eVB handles variables. All eVB variables are Variants and
when you define a String, you actually get a Variant holding
a pointer to a BSTR which is, in essence, an array of characters.
The ReadFile API requires a String variable
to store the data it reads, but the String you pass in must
have enough space allocated to hold that data or bad things
can occur. The easiest way to allocate space to use the
String() method. For example to make a 255 character String
holding all empty characters, you would do this:
MyString = String(255, 0)
Third, you need to be know about the
binary functions MidB, LeftB,
RightB, AscB
and ChrB. These all are analogous
to their String counterparts (same function names sans the
"B" suffix) but work 1 byte at a time. This is
crucial when working in CE because, once again, CE uses
Unicode (2 bytes per character) strings.
Finally you'll need to understand how
to make API calls from eVB and probably be able to build
binary Strings (for passing binary data as a String). These
are both well covered in Tim and I's book, in other tutorials
here on DEVBUZZ as
well as other places on the Web.
Opening a File
Whether you want to read from or write
to a file, the first order of business is to open it. This
is done with the CreateFile API. How you intend to use it
(i.e. for writing, reading appending) and other file options
(always create the file, fail if it exists, etc.) are passed
as parameters when you call CreateFile and CreateFile will
return a handle to the opened file.
CreateFile must always be paired with
a CloseHandle call to close the file. Make sure you keep
that in mind even in error handlers.
If we want to read a file, we can use
the following:
hFile = CreateFile(txtFileName.Text, GENERIC_READ
+ GENERIC_WRITE, _
0, 0, OPEN_EXISTING, 0, 0)
This will only open an existing file.
If the file doesn't exist, hFile will return -1. The Err
object will not be populated and if you want more information
about the failure you can get it by calling the GetLastError
API.
If we want to write to a file, creating
it if it doesn't exist, we can use this:
hFile = CreateFile(txtFileName.Text, GENERIC_READ
+ GENERIC_WRITE, _
0, 0, CREATE_ALWAYS, 0, 0)
Writing to a File
Once we've opened the file, writing
to it is done with the WriteFile API. We pass WriteFile
our file handle, our data String, the length of our String
and a numeric variable and a null (which is just a zero)
like this:
WriteFile hFile, MyString, LenB(MyString),
lWritten, 0
The things to note here are the use
of LenB instead of Len. Again, with Unicode if MyString
contained "Hello" Len will return the number of
characters in MyString - in this case five - while LenB
will return the length of the string in bytes, which is
actually 10.
Next Page