represents a collection of file-handling code snippets I have put together over a few years working on NT client/server systems. My main reason for writing these functions was to make it easier to implement such systems - I wanted consistent interfaces, plenty of diagnostics about what was going on, and extensions that go beyond anything in the Win32 API. I also wanted to make it independent of MFC, because some older systems I work on use only Win32 SDK.
When I started pulling together different pieces of code for
CXFile, one of the first things I realized was that I would have to do something about all the
TRACE statements that were scattered throughout the code. I am a big fan of using
TRACE statements as a way to monitor actual system operation, but I was afraid I would have to yank all
TRACE statements out because I did not want to be tied to MFC. I was very reluctant to do this, because alternative is to put debug output statements in application code, which becomes very messy.
Luckily I found an article by Paul Mclachlan, "Getting around the need for a vararg #define just to automatically use __FILE__ and __LINE__ in a TRACE macro". Paul's
TRACE replacement is not only free of MFC dependency, it also provides file and line number output, is thread-safe, and is completely encapsulated in one header file. I have made some minor changes to Paul's class (such as adding thread ID to the output), and so I renamed it to XTrace.h to prevent any conflicts.
With the big
TRACE problem out of the way, I could now decide how to use
TRACE in a consistent manner. I decided I wanted diagnostics of two types: a basic informational-type debug message, that reports values and code flow; and an error diagnostic for API failures and other serious problems. So I use the standard
TRACE macro for debug messages, and a new
TRACEERROR macro for API failures. It is easy to disable one or both of these macros, by replacing them with usual
#define TRACE ((void)0)
definition, and I have included this capability in XFile.cpp
CXFile features. In addition to basic file operations such as opening/creating, reading, writing, copying, deleting, and renaming files,
CXFile includes extended functions:
When writing files,
will only write whatever data is in byte buffer that is passed to it, with one exception: if
object has been constructed with the Unicode flag set to TRUE, or has been opened with the Unicode flag set to TRUE, then
will write Unicode header (see above) when writing data at beginning of file. This flag should be used only for plain text files.
When reading files,
will read whatever data is in file, and return it in buffer passed to it. No CR/LF
or any other type of conversion is done.
The zip engine used in
does not care what type of data is in files that you zip. However, the names of the files being zipped are handled as ANSI internally by zip engine. If you look at XZip.cpp
function is prototyped as
ZRESULT ZipAdd(HZIP hz, const TCHAR *dstzn, void *src, unsigned int len,
parameter is converted from Unicode to ANSI, and this ANSI string is used as the entry name within the zip archive. The
parameter is name of source file (that will be compressed by
), and should also be passed as a Unicode string if
How To Use
CXFile class into your app, you first need to add following files to your project:
file is optional, and can be excluded. If you exclude it, comment out
line from XFile.cpp
, and uncomment
#define TRACEERROR ((void)0)
line. The XZip.cpp
files are also optional, if you do not need
function. Uncomment line
at top of XFile.cpp
If you include
CXFile in project that uses precompiled headers, you must change C/C++ Precompiled Headers settings to Not using precompiled headers for XFile.cpp and XZip.cpp.
Next, include the header file XFile.h in appropriate project files (stdafx.h usually works well). Now you are ready to start using
CXFile. There are many notes concerning usage of various functions in XFile.cpp. Please read all function header for each function you wish to use.
There are two ways to construct
CXFile object. Typical way is to specify file name in
file.Printf("This is test %d", nTest);
If you do not specify file name in
, you must call
file.Printf("This is test %d", nTest);
demo tests the APIs in
. Here is output from Test 1, that shows a binary file created and then read. Its contents are then checked.
Frequently Asked Questions
- Why use CXFile at all? Why not just use the Win32 file APIs?
Aside from the extended functions like
Rollover(), the main reason is to have better error reporting. Instead of having to check the return code, and then do error reporting yourself after each API call, all you have to do is check the return code -
CXFile does the error reporting for you.
- I don't want to run my app under the debugger all the time, just to get the TRACE output. How can I see all this error reporting?
You can use the excellent free utility DebugView from Sysinternals. This allows you to see all TRACE output from your debug builds. One very nice feature of DebugView that I cannot live without is the ability to filter the output, and colorize any line that contains a particular string. For example, you can set the filter to color any line containing "error" with red background and white text. You can probably guess what my filters are from this screenshot:
- Can I use XFile in non-MFC apps?
Yes. It has been implemented to compile with any Win32 program.
- When I try to include XFile.cpp in my MFC project, I get the compiler error
XFile.cpp(2611) : fatal error C1010: unexpected end of file while looking for precompiled header directive. How can I fix this?
When using XFile in project that uses precompiled headers, you must change C/C++ Precompiled Headers settings to Not using precompiled headers for XFile.cpp and XZip.cpp. Be sure to do this for All Configurations.
- When I try to build the demo app, I get the linker error
LINK : fatal error LNK1104: cannot open file "mfc42u.lib" Error executing link.exe. How can I fix this?
The default installation options of Visual C++ v6.0 don't install the Unicode libraries of MFC, so you might get an error that mfc42u.lib or mfc42ud.lib cannot be found. You can fix this either by installing the Unicode libs from the VC++ install CD, or by going to Build | Set Active Configuration and selecting one of the non-Unicode configurations.
You can configure the Visual Studio toolbars to include the Select Active Configuration combobox. This lets you see at a glance what configuration you are working with.
- I am trying to use mapped reads, but I get a debug assertion in XFile.cpp. What's wrong?
Check the TRACE output. If you see a line that says WARNING: file offset is not a multiple of system's virtual memory, then you are trying to use an invalid file offset. With mapped reads, the file offset (and therefore the read buffer size) must be a multiple of the system's virtual memory allocation granularity, or the next call to
MapViewOfFile() will fail. Here is what MSDN says about this:
|The combination of the high and low offsets must specify an offset within the file that matches the system's memory allocation granularity, or [MapViewOfFile] fails. That is, the offset must be a multiple of the allocation granularity. Use the GetSystemInfo function, which fills in the members of a SYSTEM_INFO structure, to obtain the system's memory allocation granularity. |
You can use
CXFile::GetAllocationGranularity() to retrieve the system's memory allocation granularity and allocate a buffer. Search for "granularity" in XFile.cpp for more information.
- I don't need the Zip function. Can I exclude XZip.cpp?
Yes. Uncomment the following line at the top of XFile.cpp:
- Can we use XFile and XZip in our (shareware/commercial) app?
Yes, you can use XFile without charge or license fee. It would be nice to acknowledge my Copyright in your About box or splash screen, but this is up to you. XZip has its own licensing requirements. Basically, it is free to use any way you want, but you must acknowledge use in your documentation. See header of XZip.cpp for details.
- Does XFile handle pipes? mailslots? other types of devices?
XFile has not been tested with anything other than files.
Version 1.2 - 2003 May 15
- Enabled use on Win9x - removed dependency on
Shrink parameters to accept byte array rather than string, and also added parameter for byte array size. This allows sequence of non-text values to be used for delimiter.
FILE_FLAG_SEQUENTIAL_SCAN flag to
CreateFile, suggested by mattb79.
#define XFILE_ERROR ((DWORD)-1)
#define XFILE_EOF ((DWORD)-2)
Version 1.1 - 2003 May 5
This software is released into the public domain. You are free to use it in any way you like. If you modify it or extend it, please to consider posting new code here for everyone to share. This software is provided "as is" with no expressed or implied warranty. I accept no liability for any damage or loss of business that this software may cause.