Click to Rate and Give Feedback
MSDN
MSDN Library
Windows Mobile
Technical Articles
 File I/O in a C++ Application on th...
 
File I/O in a C++ Application on the Pocket PC
 

When your eMbedded Visual C++ Pocket PC application needs to create or access data files, you have several options. While there are other ways to do file Input/Output (I/O) (using the stream C++ classes, using Microsoft Foundation Classes [MFC] CDocument streaming, etc.), most applications will use either the Microsoft Win32 application programming interface (API) functions (CreateFile, ReadFile, WriteFile), or the MFC class CFile and its methods.

Applies to:
   Microsoft Windows Powered Pocket PC 2000
   Microsoft eMbedded Visual C++ version 3.0
   Microsoft eMbedded Visual Tools version 3.0

Gotchas

File names on the Pocket PC are a bit tricky at first, so I have included a section on Pocket PC file names in this article.

Languages Supported

English.

Pocket PC File Names

Because there are no drive letters in the Pocket PC file system, all fully qualified file names (file names that include the full directory path to the file) start with the backslash character, which means "the root of the device" not "the root of main storage memory" as some people suppose. CompactFlash (CF), Multimedia Cards, and PCMCIA (Personal Computer Memory Card International Association) memory cards are all considered storage cards by the Pocket PC, and are named as such, with the first card being named "Storage Card" and subsequent cards being named "Storage Card2", "Storage Card3", etc. So to access a file in the Pictures directory on a CF card, your file name might be \Storage Card\Pictures\MyFile.jpg. Directories in main memory are directly off the root, so \Windows\MyCustom.DLL would also be valid.

Other valid file names are COM1: to use direct serial-port access (depending on your device type, of course) and COM3: to use the infrared port.

File I/O Using the Win32 API Functions

The Win32 API is robust and versatile, so versatile in fact that it can be a little overwhelming when you first look at the documentation, because it is used for many types of I/O, not just data files as its name would imply. Although the parameters can be varied depending on your application's needs, my experience has shown me many times that they are almost always the same for most applications.

  1. Create or Open the file using the CreateFile() function. This same function is used for either operation, and it can be directed to overwrite an existing file, fail if a file exists, and many other options too numerous to list here.
  2. For the dwDesiredAccess parameter, specify GENERIC_READ or GENERIC_WRITE or both (using the OR operator i.e., GENERIC_READ | GENERIC_WRITE).
  3. For the dwShareMode parameter, specify FILE_SHARE_READ, which will allow other applications to read your file without locking it so that you can't write to it (this allows the file to be copied, i.e., without having to close your application).
  4. Set the security attributes to NULL, which is currently the only supported value.
  5. On a read-only file, set dwCreationDisposition to OPEN_EXISTING, which will fail if the file doesn't exist. All other times, you will most likely want to set dwCreationDisposition to OPEN_ALWAYS, which creates the file if it doesn't exist but opens it if it does.
  6. Set the attribute to FILE_ATTRIBUTE_NORMAL.
  7. Set hTemplateFile to 0, because it's ignored anyway.
  8. If CreateFile() successfully opens your file, you will receive a handle to the file. If it fails, it will return INVALID_HANDLE_VALUE, and you can call GetLastError() to determine why the file could not be opened or created.
  9. Once you have the file handle, you can move through the file with the SetFilePointer() function. You can use this function to move to a position relative to the beginning or the end of the file, or from the current position (see Figure).
  10. When you have positioned the file pointer where you want it, you can write to the file with the WriteFile() function or read from the file with the ReadFile() function (passing NULL for the lpOverlapped parameter, as overlapped I/O is an article in itself).
  11. When you are finished with the file, you should always call the CloseHandle() function.

File pointers in Win32 and MFC.

File I/O Using the MFC CFile Class

Microsoft has encapsulated the Win32 file I/O functions in a class they (quite cleverly) named CFile. While the CFile class has nearly identical functionality to the Win32 functions it wraps, there are several good reasons to use it if you are already using MFC in your application:

  • It can be used as a base class for a custom file I/O class.
  • Because the Win32 file handles are closed in the class destructor, there is less chance for a resource leak in your application (true for any type of handle-wrapper class, by the way).
  • Readability of the source code is a little better.
  • There is less chance of passing the wrong handle to a function call, because it would be caught at compile time as a syntax error instead of needing to wait until run time.

Again, the parameters might vary with your application's needs, but in general, these will work for your application every time:

  1. Construct the CFile object without passing the file name. Because constructors don't return values to indicate success or failure, and Microsoft eMbedded Visual C++ does not currently support exceptions, there is no good way to check for failure if the file cannot be opened, when you try to do it in the object constructor.
  2. Call the CFile::Open() method to open the file. As with the Win32 CreateFile() function, this method can also be used to open an existing file or create a new file.
  3. For the nOpenFlags parameter, you will generally specify one of the following: either CFile::modeReadWrite | CFile::shareDenyWrite if you are going to read and/or write the file, or simply CFile::modeRead if you are only going to read the file.
  4. For the pError parameter, pass a pointer to a CFileException object (generally just a stack variable declared immediately before the call to the Open() method). Despite its name, this will not actually cause an exception to be thrown if the Open() method fails, but it will describe why it failed in the m_cause data member of the CFileException object.
  5. Use the Seek() method to move the pointer through the file. You can seek from the beginning, current position, or end of the file by using CFile::begin, CFile::current, and CFile::end for the nFrom parameter.
  6. Once you have positioned your file pointer, you can use the Read() and Write() methods of the CFile class to access the contents of the file.
  7. There is generally no need to close the file explicitly when using CFile, because this will happen automatically when the object is deleted. There is a Close() method you can use, though, should you want to close the file while the object is still in scope.

Conclusion

If you're a desktop Microsoft Windows developer, you're probably as surprised as I was at how well Microsoft has shielded Pocket PC developers from the fact that there really is no disk on the Pocket PC (generally speaking). The file I/O available to developers is simple, robust, and complete, and if done with a little care this can be one of the easier parts of your application to complete.

© 2009 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement
Page view tracker