BDE 4.14.0 Production release
|
Provide a stream buffer initialized with a file descriptor.
This component implements a class, bdls::FdStreamBuf
, derived from the C++ standard library's bsl::streambuf
that can be associated with a file descriptor. Except for the pubimbue
function, all of the actions that can be performed on an bsl::streambuf
can be performed on a bdls::FdStreamBuf
. An bsl::streambuf
provides public methods for reading from and writing to a stream of data, which are implemented in terms of protected virtual functions. A bdls::FdStreamBuf
provides an implementation of these protected virtual members such that they operate on a given file descriptor. The file descriptor can represent a file, a pipe, or other device, and it can be associated with the bdls::FdStreamBuf
at construction, or by calling the reset
method. Note that a bsl::stream
can be initialized with a bdls::FdStreamBuf
, making it possible to associate the stream with a file descriptor.
Note that the pubimbue
function may be called, but not with any value other than bsl::locale()
. Furthermore, when called with this value, it has no effect.
The file descriptor type bdls::FilesystemUtil::FileDescriptor
used in this component is, on Unix, an int
type returned by open
, and on Windows, a HANDLE
type returned by CreateFile
. Ideally, a user would open the file and obtain the platform-independent bdls::FilesystemUtil::FileDescriptor
by calling bdls::FilesystemUtil::open
, which will call the appropriate routine for the platform and return a bdls::FilesystemUtil::FileDescriptor
. A value of bdls::FilesystemUtil::k_INVALID_FD
is used to represent an invalid file handle on both platforms.
On Windows for a file in text mode, the byte 0x1a
(ctrl-Z) is recognized as an end of file marker. If it is encountered, it is not returned in the buffer and subsequent reads will indicate that no more input is available. The behavior is undefined if it is not the last byte in the file. Other types of files are not required to end with 0x1a
. For files on Unix and files opened in binary mode on Windows, 0x1a
is treated like any other byte.
Note that the public methods of the bsl::streambuf
class used in the usage example are not described here. See documentation in "The C++ Programming Language, Third Edition", by Bjarne Stroustrup, Section 21.6.4, and on the web at:
Note that the bdls::FdStreamBuf
and bdls::FdStreamBuf_FileHandler
classes here are based on STLPort's implementation of filebuf
and _Filebuf_Base
respectively, with copyright notice as follows:
This section illustrates intended use of this component.
The most common usage of this component is to initialize a stream. In this case, the bdls::FdStreamBuf
will be used for either input or output, but not both.
First we create a suitable file name, and make sure that no file of that name already exists:
Then we create the file and open a file descriptor to it; the boolean flags indicate that the file is to be writable, and not previously existing (and therefore must be created):
Next we create a bdls::FdStreamBuf
associated with file descriptor fd
; the false
argument indicates that streamBuffer
will not assume ownership of fd
, meaning that when streamBuffer
is destroyed fd
will remain open:
Note also that the stream buffer defaults to being in text mode on Windows, and binary mode on Unix.
Note also that the stream buffer defaults to being in text mode on Windows, and binary mode on Unix.
Now create a new stream buffer to read the file back, in this case using binary mode so we can see exactly what was written. The new stream buf is used to initialize an input stream.
Finally, read the file back a second time, this time in text mode. Note how, on Windows, the \r\n
is translated back to \n
:
And finally, we clean up:
For our second example we will create a bdls::FdStreamBuf
associated with a temporary file, and then use the public methods of the base class interface, including sputn
, sgetn
and pubseekpos
, to do some I/O and seeking on it.
We start by selecting a file name for our (temporary) file.
Then, make sure the file does not already exist:
Next, Create the file and open a file descriptor to it. The boolean flags indicate that the file is writable, and not previously existing (and therefore must be created):
Now, we create a bdls::FdStreamBuf
object named streamBuffer
associated with the file descriptor fd
. Note that streamBuffer
defaults to assuming ownership of fd
, meaning that when streamBuffer
is cleared, reset, or destroyed, fd
will be closed. Note that FdStreamBuf
implements streambuf
, which provides the public methods used in this example:
Next we use the sputn
method to write two lines to the file:
Then we seek back to the start of the file.
Next, we read the first lengthLine1
characters of the file into buf
, with the method sgetn
.
Next we try to read 2 * lengthLine2
characters when only lengthLine2
characters are available in the file to read, so the sgetn
method will stop after reading lengthLine2
characters. The sgetn
method will return the number of chars successfully read:
Trying to read past the end of the file invalidated the current cursor position in the file, so we must seek from the end or the beginning of the file in order to establish a new cursor position. Note the pubseekpos
method always seeks relative to the beginning. We seek back to the start of the file:
Note that line1 and line3 are the same length:
Then we write, replacing line1
in the file with line3
:
Now we seek back to the beginning of the file:
Next we verify we were returned to the start of the file:
Then we read and verify the first line, which now contains the text of line3
:
Now we read and verify the second line, still line2
:
Next we close fd
and disconnect streamBuffer
from fd
:
Note that streamBuffer
is now no longer open, and is not associated with a file descriptor:
Finally, we clean up the file: