文件&&头文件&&源文件(C++)

来源:互联网 发布:双十一淘宝的交易额 编辑:程序博客网 时间:2024/05/21 08:04

  • 文件相关操作
    • _fsope和_wfsopen
    • fread
    • fwrite
    • fflush
    • rename
    • remove
    • _access
    • PocoDirectoryIterator
  • 头文件和源文件中的函数声明与定义
    • sprintf和sprintf_s
    • 变参数不定参数函数设计

文件相关操作

_fsope和_wfsopen

【函数原型】

FILE *_fsopen(    const char *filename,   const char *mode,   int shflag );FILE *_wfsopen(    const wchar_t *filename,   const wchar_t *mode,   int shflag );

注: _wfsopen 是 _fsopen 的宽字符版本,其他没有什么不同

【参数】

  • filename

    要打开的文件的名称。

  • mode

    允许的访问类型。

  • shflag

    允许的共享类型。

【返回值】
这些函数均返回指向流的指针。 一个 null 指针值指示错误。 如果 filename 或 mode 是 NULL 指针或空字符串,这些函数将调用无效的参数处理程序

【说明】
_fsopen 函数以流的形式打开由 filename 指定的文件并使该文件做好准备以进行后续的共享读写,如模式和 shflag 参数所定义。 _wfsopen 是 _fsopen 的宽字符版本;_wfsopen 的 filename 和 mode 参数是宽字符串。 除此以外,_wfsopen 和 _fsopen 的行为完全相同

参数mode说明

  • “r”
    打开以便读取。 如果文件不存在或找不到,_fsopen 调用将失败;

  • “w”
    打开用于写入的空文件。 如果给定文件存在,则其内容会被销毁;

  • “a”
    打开以便在文件末尾进行写入(追加);如果文件不存在,则首先创建它;

  • “r+”
    打开以便读取和写入。 (该文件必须存在);

  • “w+”
    打开用于读取和写入的空文件。 如果给定文件存在,则其内容会被销毁;

  • “a+”
    打开以便进行读取和追加;如果文件不存在,则首先创建它;

使用 “w” 和 “w+” 类型时要小心,因为它们可能会破坏现有文件。
使用 “a” 或 “a+” 访问类型打开文件时,所有写入操作均将在文件末尾进行。 使用 fseek 或 rewind 可重新定位文件指针,但在执行任何写入操作前,文件指针将始终被移回文件末尾。 因此,无法覆盖现有数据。 指定 “r+”、”w+” 或 “a+” 访问类型时,允许读取和写入(文件将处于打开状态以进行更新)。 但是,在读取与写入之间切换时,必须有中间 fsetpos、fseek 或 rewind 操作。 如果需要的话,可以为 fsetpos 或 fseek 操作指定当前位置

mode后还可以追加以下模式:

  • “t”
    在文本(转换)模式下打开文件。 在这种模式下,输入时,回车换行 (CR-LF) 组合将转换为单一的换行 (LF);输出时,LF字符将转换为 CR-LF 组合。 CTRL+Z 也将在输入时解释为文件尾字符。 在打开以进行读取或读取/写入的文件中,_fsopen将检查文件末尾的 Ctrl+Z 并在可能的情况下将其移除。 这是因为使用 fseek 和 ftell 在以 CTRL+Z结尾的文件中移动时,可能会导致 fseek 在文件末尾附近运行不当;
  • “b”
    在二进制(未转换)模式下打开文件;禁止上述转换;

参数shflag说明:

  • _SH_COMPAT
    为 16 位应用程序设置兼容性模式;
  • _SH_DENYNO
    允许读取和写入;
  • _SH_DENYRD
    拒绝对文件的读取访问;
  • _SH_DENYRW
    拒绝对文件的读取和写入访问;
  • _SH_DENYWR
    拒绝对文件的写入访问;

fread

【函数原型】
用于从文件流中读取数据

size_t  fread(void *buffer, size_t size, size_t count, FILE * stream);

【参数】

  • buffer为接收数据的地址;
  • size为一个单元的大小;
  • count为单元个数;
  • stream为文件流;

fread()函数每次从stream中最多读取count个单元,每个单元大小为size个字节,将读取的数据放到buffer;文件流的位置指针后移 size * count 字节。

【返回值】
返回实际读取的单元个数。如果小于count,则可能文件结束或读取出错;可以用ferror()检测是否读取出错,用feof()函数检测是否到达文件结尾。如果size或count为0,则返回0。

【注意】
与fread()相对应的函数为fwrite(),fread() 和 fwrite() 一般用于二进制文件的输入输出,ASCII文件还是不要考虑了

fwrite

【函数原型】
用来将数据写入文件流中

size_t fwrite(const void * ptr, size_t size, size_t nmemb, FILE * stream);

【参数】

  • stream
    为已打开的文件指针;
  • ptr
    指向欲写入的数据地址;
  • size
    写入的单位长度;
  • nmemb
    总共写入单位长度的数量;

【返回值】
返回实际写入的nmemb数量

fflush

【函数原型】
用于清空文件缓冲区,如果文件是以写的方式打开 的,则把缓冲区内容写入文件

int fflush(FILE* stream);

【参数】
stream为文件指针
【返回值】
成功返回0,失败返回EOF,错误代码存于errno 中。指定的流没有缓冲区或者只读打开时也返回0值

rename

【函数原型】
用于重命名文件、改变文件路径或更改目录名称

 int rename(char * oldname, char * newname);

【参数】

  • oldname为旧文件名;
  • newname为新文件名;

【返回值】
修改文件名成功则返回0,否则返回-1;

【说明】

重命名文件:

  • 如果newname指定的文件存在,则会被删除;
  • 如果newname与oldname不在一个目录下,则相当于移动文件;

重命名目录:

  • 如果oldname和oldname都为目录,则重命名目录;
  • 如果newname指定的目录存在且为空目录,则先将newname删除;
  • 对于newname和oldname两个目录,调用进程必须有写权限;
  • 重命名目录时,newname不能包含oldname作为其路径前缀;例如,不能将/usr更名为/usr/foo/testdir,因为老名字(/usr/foo)是新名字的路径前缀,因而不能将其删除;

remove

【函数原型】
用于删除指定的文件

 int remove(char * filename);

【参数】
filename为要删除的文件名,可以为一目录。如果参数filename 为一文件,则调用unlink()处理;若参数filename 为一目录,则调用rmdir()来处理;

【返回值】
成功则返回0,失败则返回-1,错误原因存于errno。

【错误代码】

  • EROFS 欲写入的文件为只读文件;

  • EFAULT 参数filename 指针超出可存取内存空间;

  • ENAMETOOLONG 参数filename 太长;

  • ENOMEM 核心内存不足;

  • ELOOP 参数filename 有过多符号连接问题;

  • EIO I/O 存取错误;

_access

判断文件的访问权限
【函数原型】

int _access( const char *path, int mode );  

【参数】

  • path 文件或目录路径

  • ode 访问权限设定

【返回值】

  • 如果文件具有指定的访问权限,则函数返回 0
  • 如果文件不存在或者不能访问指定的权限,则返回-1

【说明】

  • 当path为文件时,_access函数判断文件是否存在,并判断文件是否可以用mode值指定的模式进行访问;
  • 当path为目录时,_access只判断指定的目录是否存在;
  • mode的值和含义
    00 检查文件是否存在
    02 写权限
    04 读权限
    06 读写权限

    Poco::DirectoryIterator

    DirectoryIterator是Poco类库中的一个接口函数

 Poco::DirectoryIterator it(string FilePath)

用于列举指定目录下所有的文件,参数FilePath是指定的目录

头文件和源文件中的函数声明与定义

在一个工程中函数只能被定义一次,而函数的声明可以有很多次。通常不建议在头文件中进行函数的定义,因为当头文件被多个源文件包含时实际上就是将该段函数的定义代码复制加载到当前源文件之中,即被重复定义了,此时编译器会提示函数重复定义的错误。
举例01:
函数func01在源文件b.cpp中定义,声明在a.h头文件中,此时也需要在源文件b.cpp中添加a.h头文件。其他源文件如f.cpp需要调用func01函数时,在c.cpp中包含头文件a.h即可。
举例02:
但在类中有些成员函数是必须在类声明(包含类声明的头文件)中定义的,如类的静态成员函数,inline函数。

sprintf和sprintf_s

【函数原型】
int sprintf(char *buffer,const char *format [,argument] …);

int sprintf_s(char *buffer,size_t sizeOfBuffer,const char *format [,argument] …);

【常见用法】

//把整数123 打印成一个字符串保存在s 中。sprintf(s, "%d", 123); //产生"123"可以指定宽度,不足的左边补空格:sprintf(s, "%8d%8d", 123, 4567); //产生:" 123 4567"当然也可以左对齐:sprintf(s, "%-8d%8d", 123, 4567); //产生:"123 4567"也可以按照16 进制打印:sprintf(s, "%8x", 4567); //小写16 进制,宽度占8 个位置,右对齐sprintf(s, "%-8X", 4568); //大写16 进制,宽度占8 个位置,左对齐

【区别】
1、sprintf仅仅检查format 或者缓冲区是否是空指针,如果有错误则返回相应的错误代码,若格式化数据的长度大于缓冲区的长度,便会出现溢出;

2、sprintf_s在通过参数sizeOfBuffer检查缓存区,若缓冲区不够大时会失败,失败时缓冲区中是一个空字符串;

变参数/不定参数函数设计

所用函数为vsprintf/vsprintf_s/wvsprintf/wvsprintf_s,其中vsprintf_s是vsprintf的安全版本,带w前缀的是宽字符版本
【函数原型】

int vsprintf(char *string, char *format, va_list param);

【说明】
vsprintf 是sprintf 的一个变形,它只有三个参数。vsprintf 用于执行有不定数量参数的函数,类似printf 格式。vsprintf的前两个参数与sprintf相同:一个用于保存结果的字符串缓冲区和一个格式化字符串。第三个参数是指向格式化参数队列的指针。实际上,该指针指向在堆栈中供函数调用的变量。va_list、va_start和va_end宏(在STDARG.H中定义)帮助我们处理堆栈指针。本章最后的SCRNSIZE程式展示了使用这些宏的方法
【示例】

int sprintf (char * szBuffer, const char * szFormat, ...){int     iReturn ;va_list pArgs ;va_start (pArgs, szFormat) ;iReturn = vsprintf (szBuffer, szFormat, pArgs) ;va_end (pArgs) ;return iReturn ;}
0 0
原创粉丝点击