Add wxTempFFile, similar to wxTempFile but using buffered I/O
Also add wxTempFFileOutputStream. Closes #18673.
This commit is contained in:
@@ -1,11 +1,144 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: ffile.h
|
||||
// Purpose: interface of wxFFile
|
||||
// Purpose: interface of wxTempFFile, wxFFile
|
||||
// Author: wxWidgets team
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
@class wxTempFFile
|
||||
|
||||
wxTempFFile provides a relatively safe way to replace the contents of the
|
||||
existing file. The name is explained by the fact that it may be also used as
|
||||
just a temporary file if you don't replace the old file contents.
|
||||
|
||||
Usually, when a program replaces the contents of some file it first opens it for
|
||||
writing, thus losing all of the old data and then starts recreating it.
|
||||
This approach is not very safe because during the regeneration of the file bad
|
||||
things may happen: the program may find that there is an internal error preventing
|
||||
it from completing file generation, the user may interrupt it (especially if file
|
||||
generation takes long time) and, finally, any other external interrupts (power
|
||||
supply failure or a disk error) will leave you without either the original file
|
||||
or the new one.
|
||||
|
||||
wxTempFFile addresses this problem by creating a temporary file which is meant to
|
||||
replace the original file - but only after it is fully written. So, if the user
|
||||
interrupts the program during the file generation, the old file won't be lost.
|
||||
Also, if the program discovers itself that it doesn't want to replace the old
|
||||
file there is no problem - in fact, wxTempFFile will @b not replace the old
|
||||
file by default, you should explicitly call wxTempFFile::Commit() to do it.
|
||||
Calling wxTempFFile::Discard() explicitly discards any modifications: it
|
||||
closes and deletes the temporary file and leaves the original file unchanged.
|
||||
If you call neither Commit() nor Discard(), the destructor will
|
||||
call Discard() automatically.
|
||||
|
||||
To summarize: if you want to replace another file, create an instance of
|
||||
wxTempFFile passing the name of the file to be replaced to the constructor.
|
||||
(You may also use default constructor and pass the file name to wxTempFFile::Open.)
|
||||
Then you can write to wxTempFFile using wxFFile-like functions and later call
|
||||
wxTempFFile::Commit() to replace the old file (and close this one) or call
|
||||
wxTempFFile::Discard() to cancel the modifications.
|
||||
|
||||
@since 3.1.4
|
||||
|
||||
@library{wxbase}
|
||||
@category{file}
|
||||
*/
|
||||
class wxTempFFile
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Associates wxTempFFile with the file to be replaced and opens it.
|
||||
|
||||
@warning
|
||||
You should use IsOpened() to verify that the constructor succeeded.
|
||||
*/
|
||||
wxTempFFile(const wxString& strName);
|
||||
|
||||
/**
|
||||
Destructor calls Discard() if temporary file is still open.
|
||||
*/
|
||||
~wxTempFFile();
|
||||
|
||||
/**
|
||||
Validate changes: deletes the old file of name m_strName and renames the new
|
||||
file to the old name. Returns @true if both actions succeeded.
|
||||
|
||||
If @false is returned it may unfortunately mean two quite different things:
|
||||
either that the old file couldn't be deleted or that the new file
|
||||
couldn't be renamed to the old name.
|
||||
*/
|
||||
bool Commit();
|
||||
|
||||
/**
|
||||
Discard changes: the old file contents are not changed, the temporary
|
||||
file is deleted.
|
||||
*/
|
||||
void Discard();
|
||||
|
||||
/**
|
||||
Flush the data written to the file to disk.
|
||||
|
||||
This simply calls wxFFile::Flush() for the underlying file and may be
|
||||
necessary with file systems such as XFS and Ext4 under Linux. Calling
|
||||
this function may however have serious performance implications and
|
||||
also is not necessary with many other file systems so it is not done by
|
||||
default -- but you can call it before calling Commit() to absolutely
|
||||
ensure that the data was indeed written to the disk correctly.
|
||||
*/
|
||||
bool Flush();
|
||||
|
||||
/**
|
||||
Returns @true if the file was successfully opened.
|
||||
*/
|
||||
bool IsOpened() const;
|
||||
|
||||
/**
|
||||
Returns the length of the file.
|
||||
|
||||
Returns ::wxInvalidOffset if the length couldn't be determined.
|
||||
|
||||
Please also note that there is @e no guarantee that reading that many
|
||||
bytes from the file will always succeed. While this is true for regular
|
||||
files (unless the file size has been changed by another process in
|
||||
between Length() and Read() calls), some special files, such as most
|
||||
files under @c /sys or @c /proc directories under Linux, don't actually
|
||||
contain as much data as their size indicates.
|
||||
*/
|
||||
wxFileOffset Length() const;
|
||||
|
||||
/**
|
||||
Open the temporary file, returns @true on success, @false if an error
|
||||
occurred.
|
||||
@a strName is the name of file to be replaced. The temporary file is always
|
||||
created in the directory where @a strName is. In particular, if @a strName
|
||||
doesn't include the path, it is created in the current directory and the
|
||||
program should have write access to it for the function to succeed.
|
||||
*/
|
||||
bool Open(const wxString& strName);
|
||||
|
||||
/**
|
||||
Seeks to the specified position and returns @true on success.
|
||||
*/
|
||||
bool Seek(wxFileOffset ofs, wxSeekMode mode = wxFromStart);
|
||||
|
||||
/**
|
||||
Returns the current position.
|
||||
*/
|
||||
wxFileOffset Tell() const;
|
||||
|
||||
/**
|
||||
Writes the contents of the string to the file, returns @true on success.
|
||||
|
||||
The second argument is only meaningful in Unicode build of wxWidgets when
|
||||
@a conv is used to convert @a str to multibyte representation.
|
||||
*/
|
||||
bool Write(const wxString& str, const wxMBConv& conv = wxMBConvUTF8());
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@class wxFFile
|
||||
|
||||
|
@@ -51,6 +51,54 @@ public:
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@class wxTempFFileOutputStream
|
||||
|
||||
wxTempFFileOutputStream is an output stream based on wxTempFFile.
|
||||
It provides a relatively safe way to replace the contents of the
|
||||
existing file.
|
||||
|
||||
@since 3.1.4
|
||||
|
||||
@library{wxbase}
|
||||
@category{streams}
|
||||
|
||||
@see wxTempFFile
|
||||
*/
|
||||
class wxTempFFileOutputStream : public wxOutputStream
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Associates wxTempFFileOutputStream with the file to be replaced and opens it.
|
||||
|
||||
@warning
|
||||
You should use wxStreamBase::IsOk() to verify if the constructor succeeded.
|
||||
|
||||
Call Commit() or wxOutputStream::Close() to replace the old file and close
|
||||
this one. Calling Discard() (or allowing the destructor to do it) will
|
||||
discard the changes.
|
||||
*/
|
||||
wxTempFFileOutputStream(const wxString& fileName);
|
||||
|
||||
/**
|
||||
Validate changes: deletes the old file of the given name and renames the new
|
||||
file to the old name. Returns @true if both actions succeeded.
|
||||
|
||||
If @false is returned it may unfortunately mean two quite different things: either that
|
||||
either the old file couldn't be deleted or that the new file couldn't be renamed
|
||||
to the old name.
|
||||
*/
|
||||
virtual bool Commit();
|
||||
|
||||
/**
|
||||
Discard changes: the old file contents are not changed, the temporary file is
|
||||
deleted.
|
||||
*/
|
||||
virtual void Discard();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@class wxFFileOutputStream
|
||||
|
||||
|
Reference in New Issue
Block a user