文件流要使用的io基础类的枚计类型
classios_base {
public:
enum__seekdir {
beg = 0x01, // 开始
cur = 0x02, // 当前
end = 0x04 // 结尾
};
enum__iostate {
goodbit = 0x00,
badbit = 0x01,
eofbit = 0x02,
failbit = 0x04
};
enum__openmode {
app = 0x01,
ate = 0x02,
binary = 0x04,
in = 0x08,
out = 0x10,
trunc = 0x20
};
};
_Filebuf_base文件缓冲基类
class _Filebuf_base {
protected:
_Filebuf_base();
// 打开和关闭文件缓冲区
bool _M_open(constchar*, ios_base::openmode, long __protection);
bool _M_open(constchar*, ios_base::openmode);
bool _M_open(int __id);
bool _M_close();
protected:
// 低级I/O读写
ptrdiff_t _M_read(char* __buf, ptrdiff_t __n);
bool _M_write(char* __buf, ptrdiff_t __n);
// 设置文件偏移位置和文件大小
streamoff _M_seek(streamoff __offset, ios_base::seekdir __dir);
streamoff_M_file_size();
protected:
// 内存映射I/O
void* _M_mmap(streamoff __offset, streamoff __len);
void _M_unmap(void* __mmap_base, streamoff __len);
protected:
// Returns a value n such that, if pos is the file pointer at the
// beginning of the range [first, last), pos + n is the file pointer at
// the end. On many operating systems n == __last - __first.
streamoff _M_get_offset(char* __first, char* __last);
// Returns true if we're in binary mode or if we're using an OS or file
// system where there is no distinction between text and binary mode.
bool _M_in_binary_mode() const;
protected:
#ifdef _MSC_VER
int _M_hFileMappingObject; // 映射对象句柄
#endif
int _M_file_id; // 文件句柄
ios_base::openmode _M_openmode; // 打开模式
int _M_page_size; // 页的大小
bool _M_is_open : 1;
bool _M_should_close : 1;
bool _M_regular_file : 1;
};
文件缓冲区类
template <class_CharT, class_Traits>
classbasic_filebuf : publicbasic_streambuf<_CharT, _Traits>,
private _Filebuf_base
{
public: // Types.
typedef_CharT char_type;
typedeftypename_Traits::int_type int_type;
typedeftypename_Traits::pos_type pos_type;
typedeftypename_Traits::off_type off_type;
typedef_Traits traits_type;
typedeftypename_Traits::state_type _State_type;
typedefbasic_streambuf<_CharT, _Traits> _Base;
public: basic_filebuf();
~basic_filebuf();
public:
// 关闭和打开文件
boolis_open() const;
basic_filebuf* open(constchar*, ios_base::openmode);
// 扩展版本open()
basic_filebuf* open(constchar*, ios_base::openmode, long__protection);
basic_filebuf* open(int__id);
basic_filebuf* close();
protected:
// basic_streambuf基类的重载的虚函数
virtualstreamsizeshowmanyc();
virtualint_typeunderflow();
virtualint_typepbackfail(int_type = _Traits::eof());
virtualint_typeoverflow(int_type = _Traits::eof());
virtualbasic_streambuf<_CharT, _Traits>* setbuf(char_type*, streamsize);
virtualpos_typeseekoff(off_type, ios_base::seekdir,
ios_base::openmode = ios_base::in | ios_base::out);
virtualpos_typeseekpos(pos_type,
ios_base::openmode = ios_base::in | ios_base::out);
virtualintsync();
virtualvoidimbue(constlocale&);
private:
// 内部帮助函数
// 模式
void_M_exit_putback_mode();
bool_M_switch_to_input_mode();
void_M_exit_input_mode();
bool_M_switch_to_output_mode();
int_type_M_input_error();
int_type_M_underflow_aux();
friendclass _Noconv_output<_Traits>;
friendclass _Noconv_input<_Traits>;
friendclass _Underflow< basic_filebuf<_CharT, _Traits> >;
int_type_M_output_error();
bool_M_unshift();
// 分配缓存区
bool_M_allocate_buffers(_CharT* __buf, int__n);
bool_M_allocate_buffers();
void_M_deallocate_buffers();
// 定位缓冲区
pos_type_M_seek_return(off_type, _State_type);
bool_M_seek_init(bool__do_unshift);
// 设置字符集转换
void_M_setup_codecvt(constlocale&);
private:
// 文件缓冲区用户看到的内部字符缓冲区:
_CharT* _M_int_buf;
_CharT* _M_int_buf_EOS;
// 对应扩展文件字符的扩展缓冲区
char* _M_ext_buf;
char* _M_ext_buf_EOS;
// 对应内部缓冲区的开始状态
_State_type_M_state;
private:
// 只在输入模式使用的数据成员
// [_M_ext_buf, _M_ext_buf_converted] 包含了扩展字符对应内部缓冲区
// [_M_ext_buf_converted, _M_ext_buf_end] 包含已经读入扩展缓冲区当没有转换内部equence.
char* _M_ext_buf_converted;
char* _M_ext_buf_end;
// 类似_M_state 对应内部缓冲区结尾状态
_State_type_M_end_state;
// 除非使用内存映射文件,否则为空指针
void* _M_mmap_base;
streamoff_M_mmap_len;
private:
// 只在输出模式使用的数据成员
_CharT* _M_saved_eback;
_CharT* _M_saved_gptr;
_CharT* _M_saved_egptr;
enum { _S_pback_buf_size = 8 };
_CharT_M_pback_buf[_S_pback_buf_size];
private:
// 本地化信息(不关心)
typedefcodecvt<_CharT, char, _State_type> _Codecvt;
const_Codecvt* _M_codecvt;
int_M_width; // 编码宽度(if constant), else 1
int_M_max_width; // 单个字符最低宽度
bool_M_constant_width : 1;
bool_M_always_noconv : 1;
private:
//模式标记
bool_M_int_buf_dynamic : 1; // True 内部缓冲区是堆分配
// false 由用户提供
bool_M_in_input_mode : 1;
bool_M_in_output_mode : 1;
bool_M_in_error_mode : 1;
bool_M_in_putback_mode : 1;
};
这个成员必须流在执行任何IO操作之前调用,否则没有作用
// __buf == 0 && __n == 0 means to make ths stream unbuffered.
// __buf != 0 && __n > 0 means to use __buf as the stream's internal
// buffer, rather than the buffer that would otherwise be allocated
// automatically. __buf must be a pointer to an array of _CharT whose
// size is at least __n.
template <class_CharT, class_Traits>
basic_streambuf<_CharT, _Traits>*
basic_filebuf<_CharT, _Traits>::setbuf(_CharT* __buf, streamsize__n)
{
if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode &&
_M_int_buf == 0) {
if (__buf == 0 && __n == 0)
_M_allocate_buffers(0, 1);
elseif (__buf != 0 && __n > 0)
_M_allocate_buffers(__buf, __n);
}
returnthis;
}
seekoff()
// __off是偏移量(整型), __whence是方向(枚计类型)从开始,当前,结尾偏移),该函数主要还是调用另外一个方法基类的函数_M_seek实现, _M_seek则调用lseek系统函数实现
_M_seek定义如下:参数(偏移量和方向),放回lseek的返回值
_M_seek(streamoff offset, ios_base::seekdir dir)
template <class_CharT, class_Traits>
typenamebasic_filebuf<_CharT, _Traits>::pos_type
basic_filebuf<_CharT, _Traits>::seekoff(off_type__off,
ios_base::seekdir __whence,
ios_base::openmode/* dummy */)
{
if (this->is_open() &&
(__off == 0 || (_M_constant_width && this->_M_in_binary_mode())))
{
// 定位初始化
if (!_M_seek_init(__off != 0 || __whence != ios_base::cur))
returnpos_type(-1);
//从到头或尾定位,不管是否输入模式
if (__whence == ios_base::beg || __whence == ios_base::end)
return _M_seek_return(this->_M_seek(_M_width * __off, __whence),
_State_type());
// 从当前位置定位,如果在输入模式问题就复杂化
elseif (__whence == ios_base::cur) {
if (!_M_in_input_mode)
return _M_seek_return(this->_M_seek(_M_width * __off, __whence),
_State_type());
// 使用了内存映射.
elseif (_M_mmap_base != 0) {
// __off is relative to gptr(). We need to do a bit of arithmetic
// to get an offset relative to the external file pointer.
streamoff __adjust = this->gptr() - (_CharT*) _M_mmap_base;
return _M_seek_return(this->_M_seek(__off + __adjust - _M_mmap_len,
ios_base::cur),
_State_type());
}
// 使用固定字符宽度
elseif