S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

(Windows编程 文件专题)打开,读取,写入和关闭文件

关键词
C++ CreateFile CloseHandle ReadFile WriteFile API 文件句柄

  ◆CreateFile

HANDLE CreateFile(
  LPCTSTR lpName,
   DWORD dwAccess,
   DWORD dwShareMode,
   LPSECURITY_ATTRIBUTES lpSecurityAttributes,
   DWORD dwCreate,
   DWORD dwAttrsAndFlags,
   HANDLE hTemplateFile)
返回值:所创建文件对象的句柄,如果文件创建失败则返回
INVALID_HANDLE_VALUE

  lpName 是以null结尾的对文件,管道或其他打开和创建的命名对象进行命名的字符串的指针.
  dwAccess 使用 GENERIC_READ 和 GENERIC_WRITE 来指定读写访问(见WINNT.H中宏定义),允许使用位操作符(或)合并
  dwShareMode是以下二进制方式的(或)操作
    ● 0——文件不能共享,甚至该进程不能打开该文件的第二个句柄
    ● FILE_SHARE_READ——其他进程包括调用进程可以打开该文件进行并发读访问
    ● FILE_SHARE_WRITE——它允许对文件进行并发写操作
  lpSecurityAttributes 指向了 SECRITY_ATTRIBUTES 结构。
  dwCreate指定了是否创建一个新的文件,是否重写现有的文件等等,允许(或)操作
    ● CREATE_NEW——如果指定的文件已经存在,操作失败,否则创建新的文件
    ● CREATE_ALWAYS ——现有的文件将被改写
    ● OPEN_EXISTING——如果文件不存在,操作失败
    ● OPEN_ALWAYS——打开文件,如果文件不存在则创建
    ● TRUNCATE_EXISTING——文件长度设为零,需要dwCreate指定GENERIC_WRITE,
      如果文件已存在,所有内容将会破坏
  dwAttrsAndFlags 指定了文件属性和标记。有16个标记和属性
    ● FILE_ATTRIBUTE_NORMAL 该属性只有在其他属性没有设置时才有用
    ● FILE_ATTRIBUTE_READONLY 程序不能改写也不能删除文件
    ● FILE_FLAG_DELETE_ON_CLOSE 对于临时文件很有用。
      当最后一个HANDLE关闭时,文件就被删除
    ● FILE_FLAG_OVERLAPPED 该属性标记对于异步I/O很重要
    ● FILE_FLAG_WRITE_THROUGH 直接对磁盘文件进行中间缓存写操作
    ● FILE_FLAG_NO_BUFFERING 没有中间缓存,数据传输直接在程序中由 ReadFile和      
      WriteFile 调用指定的数据缓存上实现。相应地,在扇区地边界处也需要缓存,而且完
      整地扇区必须被传输。在使用该标记时,通过调用函数 GetDiskFreeSpace 来决定扇
      区的大小
    ● FILE_FLAG_RANDOM_ACCESS 主要用于随机访问,而 Windows 也会尽量优化文件
      缓存
    ● FILE_FLAG_SEQUENTIAL_SCAN 主要用于顺序访问,而 Windows也会对文件缓存作
      相应优化
  hTemplateFile 是打开的 GENERIC_READ 文件的句柄,该文件指定了用于新创建的文件的扩展属性,并忽略了 dwAttrsAndFlags。通常参数是NULL,当现有的文件已打开时,hTemplateFile 被忽略。该参数可用来将新文件的属性设置成跟现有文件的属性相同

  如果文件共享属性和安全性允许,文件会有许多打开的句柄。打开的句柄可以由相同或不同的进程所拥有

  ◆关闭文件

BOOL CloseHandle(HANDLE hObject)
返回值:如果本函数成功执行,返回TRUE,否则返回FALSE。

  一个万能的函数关闭,句柄会销毁,所有对象的系统资源也会释放。当然也会有异常情况。关闭句柄也减少了对象的句柄引用计数,这样非永久的对象比如临时文件和事件将被删除。系统在退出时会关闭所有打开句柄,但是在程序终止前关闭其句柄是个很好的习惯。
  关闭一个无效的句柄或对同一个句柄关闭两次将会引起异常,而关闭标准设备句柄是不必要的或不适宜的

  ◆读取文件

BOOL ReadFile(
  HANDLE hFile,
  LPVOID lpBuffer,
  DWORD nNumberOfBytesToRead,
  LPDWORD lpNumberOfBytesRead,
  LPOVERLAPPED lpOverlapped)
返回值:如果文件读取操作成功执行,则返回TRUE(即使试图读取文件末尾后的内容,未能读取到任何字节,仍旧返回TRUE)。

  hFile 是具有GENERIC_READ 访问权限的文件句柄。
  lpBuffer指向接受输入数据的内存缓存
  nNumberOfBytesToRead 是从文件中读取的字节数,如果句柄位于文件的末尾处或有错误时,其值可以是零。消息模式的命名管道允许0长度的消息。
  lpOverlapped 指向了OVERLAPPED结构,现在使用NULL

  如果dwAttrsAndFlags中没有设置选项 FILE_FLAG_OVERLAPPED。那么ReadFile从句柄的当前文件位置开始,随着传输字节数往前移动位置。
  如果句柄或任何其它参数无效,函数失败并返回FALSE,如果文件句柄位于文件末尾处,函数不会失败,取而代之,读取字节数 (*lpNumberOfBytesRead)被设为0。

  ◆写文件

BOOL WriteFile(
  HANDLE hFile,
  LPCVOID lpBuffer,
  DWORD nNumberOfBytesToWrite,
  LPDWORD lpNumberOfBytesWritten,
  LPOVERLAPPED lpOverlapped)
返回值:如果本函数成功执行,则返回TRUE,否则返回FALSE

  注意一个成功的写操作不能确保数据真正被写入硬盘中,除非在CreateFile中指定FILE_FLAG_WRITE_THROUGH。如果句柄位于文件的末尾,Windows会扩展现有的文件的长度。
  ReadFileGather 和WriteFileGather 允许使用不同大小的缓存来进行读写操作。

  附:
示例文件(CPW.cpp)

/* 使用Windows API 实现文件复制     */
/* cpw.cpp       */

#include <windows.h>
#include <stdio.h>
#define BUF_SIZE 256

int main(int argc,LPTSTR argv[]){
HANDLE hIn,hOut;
DWORD nIn,nOut;
CHAR Buffer[BUF_SIZE];

if(argc != 3){
     printf("Usage:cpw file1 file2\n");
     return 1;
}

hIn = CreateFile(argv[1],GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
if (hIn == INVALID_HANDLE_VALUE){
     printf("Can't open input file.Error:%x\n",GetLastError());
     return 2;
}

hOut = CreateFile(argv[2],GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if (hOut == INVALID_HANDLE_VALUE){
     printf("Can't open output file.Error:%x\n",GetLastError());
     return 3;
}

while(ReadFile(hIn,Buffer,BUF_SIZE,&nIn,NULL) && nIn>0){
     WriteFile(hOut,Buffer,nIn,&nOut,NULL);
     if(nIn != nOut){
      printf("Fatal write error:%x\n",GetLastError());
      return 4;
     }
}

CloseHandle(hIn);
CloseHandle(hOut);
return 0;
}


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理