|
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: