|
wxWidgets provides a range of functionality for platform-independent file handling. We'll introduce the major classes before summarizing the file functions. wxFile and wxFFilewxFile may be used for low-level input/output. It contains all the usual functions to work with integer file descriptors (opening/closing, reading/writing, seeking, and so on), but unlike the standard C functions, it reports errors via wxLog and closes the file automatically in the destructor. wxFFile brings similar benefits but uses buffered input/output and contains a pointer to a FILE handle. You can create a wxFile object by using the default constructor followed by Create or Open, or you can use the constructor that takes a file name and open mode (wxFile::read, wxFile::write, or wxFile::read_write). You can also create a wxFile from an existing file descriptor, passed to the constructor or Attach function. A wxFile can be closed with Close, which is called automatically (if necessary) when the object is destroyed. You can get data from the object with Read, passing a void* buffer and the number of bytes to read. Read will return the actual number of bytes read, or wxInvalidOffset if there was an error. Use Write to write a void* buffer or wxString to the file, calling Flush if you need the data to be written to the file immediately. To test for the end of the file, use Eof, which will return TRue if the file pointer is at the end of the file. (In contrast, wxFFile's Eof will return TRue only if an attempt has been made to read past the end of the file.) You can determine the length of the file with Length. Seek and SeekEnd seek to a position in the file, taking an offset specified as starting from the beginning or end of the file, respectively. Tell returns the current offset from the start of the file as a wxFileOffset (a 64-bit integer if the platform supports it, or else a 32-bit integer). Call the static Access function to determine whether a file can be opened in a given mode. Exists is another static function that tests the existence of the given file. The following code fragment uses wxFile to open a data file and read all the data into an array. #include "wx/file.h" if (!wxFile::Exists(wxT("data.dat"))) return false; wxFile file(wxT("data.dat")); if ( !file.IsOpened() ) return false; // get the file size wxFileOffset nSize = file.Length(); if ( nSize == wxInvalidOffset ) return false; // read the whole file into memory wxUint* data = new wxUint8[nSize]; if ( fileMsg.Read(data, (size_t) nSize) != nSize ) { delete[] data; return false; } file.Close(); To illustrate file writing, here's a function that will dump the contents of a text control to a file. bool WriteTextCtrlContents(wxTextCtrl* textCtrl, const wxString& filename) { wxFile file; if (!file.Open(filename, wxFile::write)) return false int nLines = textCtrl->GetNumberOfLines(); bool ok = true; for ( int nLine = 0; ok && nLine < nLines; nLine++ ) { ok = file.Write(textCtrl->GetLineText(nLine) + wxTextFile::GetEOL()); } file.Close(); return ok; } wxTextFilewxTextFile provides a very straightforward way to read and write small files and process them line-by-line. Use Open to read a file into memory and split it into lines, and use Write to save it. You can use GetLine or the array operator to retrieve a specified line, or you can iterate through the file with GetFirstLine, GetNextLine, and GetPrevLine. Add lines to the file with AddLine or InsertLine, and remove lines by passing the line number to RemoveLine. You can clear the whole file with Clear. In the following example, each line of a file is prepended with a given string before being written back to the same file. #include "wx/textfile.h" void FilePrepend(const wxString& filename, const wxString& text) { wxTextFile file; if (file.Open(filename)) { size_t i; for (i = 0; i < file.GetLineCount(); i++) { file[i] = text + file[i]; } file.Write(filename); } } wxTempFilewxTempFile is derived from wxFile and uses a temporary file to write data, not writing to the actual file until Commit is called. When you write a user's data, it's a good idea to write to a temporary file because if an error occurs during the save operation (such as a power failure, program bug, or other cataclysm), this error will not corrupt the current file on disk. Note The document/view framework does not write to a temporary file when creating an output stream and calling SaveObject, so you may want to override DoSaveDocument and construct a wxFileOutputStream from a wxTempFile object. After writing data, call Sync on the stream followed by Commit on the temporary file object. wxDirwxDir is a portable equivalent of the Unix open/read/closedir functions, which support enumeration of the files in a directory. wxDir supports enumeration of files as well as directories. It also provides a flexible way to enumerate files recursively using traverse or the simpler GetAllFiles function. After opening a file with Open (or by passing a path to the constructor), call GetFirst passing a pointer to a string to receive the found file name. You can also pass a file specification (defaulting to the empty string to match all files) and optional flags. Then call GetNext until there are no more matching files and the function returns false. The file specification can contain wildcards, such as "*" (match any number of characters) and "?" (match one character). For the flags argument, pass a bit-list of wxDIR_FILES (match files), wxDIR_DIRS (match directories), wxDIR_HIDDEN (match hidden files), and wxDIR_DOTDOT (match "." and ".."). The default is to match everything except "." and "..". Here's an example of its use: #include "wx/dir.h" wxDir dir(wxGetCwd()); if ( !dir.IsOpened() ) { // Deal with the error here - wxDir already logs an error message // explaining the exact reason of the failure return; } puts("Enumerating object files in current directory:"); wxString filename; wxString filespec = wxT("*.*"); int flags = wxDIR_FILES|wxDIR_DIRS; bool cont = dir.GetFirst(&filename, filespec, flags); while ( cont ) { wxLogMessage(wxT("%s\n"), filename.c_str()); cont = dir.GetNext(&filename); } Note that if there is a problem when enumerating filesfor example, if the directory does not existwxDir will generate a log message. To suppress this behavior, use the wxLogNull object to temporarily disable logging: // Create scope for logNull { wxLogNull logNull; wxDir dir(badDir); if ( !dir.IsOpened() ) { return; } } wxFileNamewxFileName models the name of a file; it can parse and reconstitute the components of a file name, and it also provides a variety of file operations, some of which are static functions. Here are some examples of what you can do with this class. Please see the reference manual for the many other operations. #include "wx/filename.h" // Create a filename from a string wxFileName fname(wxT("MyFile.txt")); // Normalize, including making sure the filename is in its long form // on Windows fname.Normalize(wxPATH_NORM_LONG|wxPATH_NORM_DOTS|wxPATH_NORM_TILDE| wxPATH_NORM_ABSOLUTE); // Get the full path as a string wxString filename = fname.GetFullPath(); // Make it relative to the current path fname.MakeRelativeTo(wxFileName::GetCwd()); // Does the file exist? bool exists = fname.FileExists(); // Does a different file exist? bool exists2 = wxFileName::FileExists(wxT("c:\\temp.txt")); // Return the name part wxString name = fname.GetName(); // Return the path part wxString path = fname.GetPath(); // Return the short version on Windows, or identity // on other systems wxString shortForm = fname.GetShortPath(); // Makes a directory bool ok = wxFileName::Mkdir(wxT("c:\\thing")); File FunctionsThe most commonly used file functions are listed in Table 14-1, and are defined in wx/filefn.h. See also the wxFileName class, especially the static functions you can use without constructing a wxFileName object, such as wxFileName::FileExists.
wxWidgets also wraps many of the standard C file functions, such as wxFopen, wxFputc, and wxSscanf. These are not currently documented, but their definitions may be found in include/wx/wxchar.h in your wxWidgets distribution. It's also useful to know about the wxFILE_SEP_PATH symbol, which is the appropriate path separator for the platform on which the application is running (for example, backslash on Windows and forward slash on Unix-based systems). |
|