Skip to main content

Past Blast

Featured Products

Windows Mobile Developer Controls
Windows Mobile Developer Controls
Stay in touch using the DEVBUSS RSS feeds.
 

News

Windows Mobile Developer Controls
Sapphire Soltuions

eVB File Access through the WinCE API

Written by Christopher Tacke  [author's bio]  [read 64074 times]
Edited by Derek

Download the code

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