汇总收集C/C++文件读写

来源:互联网 发布:php和js 编辑:程序博客网 时间:2024/06/05 06:12

C/C++,Win32,MFC文件操作汇总

首先文件操作是无外乎是对文件打开,关闭,读写等操作,每一种语言都有对相关文件的操作接口,现在主要做一些搜集与整理,作为一些参考:
一、C语言文件操作
C语言中没有输入输出语句,所有的输入输出功能都用 ANSI C提供的一组标准库函数来实现。文件操作标准库函数有:
一、C语言文件操作
C语言中没有输入输出语句,所有的输入输出功能都用 ANSI C提供的一组标准库函数来实现。
文件操作标准库函数有:
fopen 打开一个文件
fclose 关闭一个文件
fputc 写一个字符到文件中去
fgetc 从文件中读取一个字符
fgets 从文件中读取一个字符串
fputs 写一个字符串到文件中去
fprintf 往文件中写格式化数据
fscanf 格式化读取文件中数据
fread 以二进制形式读取文件中的数据
fwrite 以二进制形式写数据到文件中去
getw 以二进制形式读取一个整数
putw 以二进制形式存贮一个整数


文件状态检查函数
feof 文件结束
ferror 文件读/写出错
clearerr 清除文件错误标志
ftell 了解文件指针的当前位置


文件定位函数 rewind 反绕
        fseek 随机定位
相关函数原型:
1.打开文件
FILE *fopen(char *pname,char *mode)
2.关闭文件
int fclose(FILE *fp);
3.从文件中读取一个字符
int fgetc(FILE *fp);
4.写一个字符到文件中去
int fputc(int ch,FILE *fp)
5.从文件中读取一个字符串
char *fgets(char *str,int n,FILE *fp)
6.写一个字符串到文件中去
int fputs(char *str,FILE *fp)
7.往文件中写格式化数据
int fprintf(FILE *fp,char *format,arg_list)
8.以二进制形式读物文件中数据
int fread(void *buffer,unsigned sife,unsigned count,FILE *fp)
9.以二进制形式写入文件数据
int fwrite(void *buffer,unsigned sife,unsigned count,FILE *fp)
10.以二进制形式读取一个整数
int getw(FILE *fp)
11.以二进制形式存储一个整数
int putw(int n,FILE *fp)
12.文件状态检查
int feof(FILE *fp)
13.文件读/写出错
int ferror(FILE *fp)
14.清除文件错误标志
void clearerr(FILE *fp)
15.文件定位
void rewind(FILE *fp)
16.随机定位
int fseek(FILE *fp,long offset,int base)
17.关于exit()函数
void exit(int status)
18.关于feof()函数
int feof(FILE *fp)


文件打开模式:
“r” 只读


从文件起始位置开始读。 注意:文件不存在时,打卡失败。


“r+” 读写(以读为主)


文件不存在时,打开失败。


文件存在时,如果没设置文件指针,文件指针指向文件首。


“w” 只写


文件不存在时,创建文件。


文件存在时,清空文件,文件指针指向文件首。


“w+” 写读(以写为主)


文件不存在时,创建文件。


文件存在时,清空文件,文件指针指向文件首。


“a” 追加写(只写)


文件不存在时,创建文件。


文件存在时,文件指针指向文件尾。(在文件为追加,即用fseek()函数无效)


“a+” 追加读写(读写)


文件不存在时,创建文件。


文件存在时:


写:追加写(文件指针设置无效)


读:先设置文件指针,写完之后文件指针在文件尾(最初,文件指针在文件首)


实例:1.利用feof()函数检查文件是否读取完毕
#include <stdio.h>
int main()
{    
FILE *fp;   
fp = fopen("d:\\curFile.txt", "r");  
if(fp != NULL){       
while(!feof(fp))         
printf("%c", fgetc(fp));   
}else{        
printf("file open failed! \n");   
}
fclose(fp);    
return 0;



2.利用文件结束标志EOF(即-1)


#include <stdio.h>


main()


{    


char ch;    
FILE *fp;    
fp = fopen("d:\\curFile.txt", "r");    
if(fp != NULL){        
ch = fgetc(fp);       
while(ch != EOF) {            
printf("%c", ch);           
ch = fgetc(fp);        
}    

}else {        
printf("file open failed! \n");  


fclose(fp);    

return 0;





3.fputc()函数的使用
#include <stdio.h>
main()
{    
FILE *fp;
if((fp=fopen("d:\\curFile.txt","w"))==NULL){
printf("a.txt open failed ! \n");
return 1;
}
int i;
for(i=0; i<10; i++){
putc('w',fp); //写10个'w'到curFile.txt文件中

fclose(fp);    
return 0;



4.fwrite函数使用
#include<stdio.h>


int main()


{


int str[10] = {1,2,3,4,5,6,7,8,9,0};

FILE *fp ;

if((fp = fopen("a.txt","w") )== NULL){

printf("file open failed!\n");


}


fwrite(str,sizeof(int),10,fp);

fclose(fp);

return 0;


}


5.fread函数:




#include<stdio.h>


int main()


{


int str[10] ;

FILE *fp ;

if((fp = fopen("a.txt","r") )== NULL){

printf("file open failed!\n");


}


fread(str,sizeof(int),10,fp);

int i;

for(i=0; i<10; i++){

printf("%d ",str[i]);


}


printf("\n");

fclose(fp);

return 0;


}


二、C++文件读写:
每种语言系统都会提供IO操作的类库,用于对预定义类型数据进行输入输出的操作。C++也是如此,它是以字节流的形式实现的。在输入操作时,字节流从输入设备(键盘、磁盘)流向内存;
在输出操作时,字节流由内存流向输出设备(显示器、打印机);字节流可以是ASCII字符、二进制数据、图形图像、音频视频等信息。文件和字符串也可以看成是有序的字节流,又称为文件
流和字符串流。C++的编译系统自带一个面向对象的输入输出软件包,即IO流类库。库中各种类的声明都被包含在相应的头文件中,比如之前经常用到的头文件iostream,其中使用的cin\cout
都是常用的流对象,用于对标准设备的IO操作。还有用于用户文件管理IO操作的fstream头文件(磁盘文件的操作),用于字符串流的IO操作的strstream头文件(内存字符流的操作),以及iomanip
头文件用于输入输出的格式控制。有两个抽象基类ios和iostream,输入流类:istream,ifstream和istrstream;输出流类:ostream,ofstream和ostrsream;输入输出流类:iostream,
fstream。ios是抽象基类,类istream和ostream是单继承于ios,而类iostream是通过多继承于类istream和类ostream。ios除了派生出istream和ostream还派生出fstreambase文件流类和
strstreambase串流类,而该4类又派生出ifstream、ofstream、istrstream、ostrstream,以及fstream和strstream。


ios::in = 0x01, //供读,文件不存在则创建(ifstream默认的打开方式)
ios::out  = 0x02, //供写,文件不存在则创建,若文件已存在则清空原内容(ofstream默认的打开方式)
ios::ate  = 0x04, //文件不存在时,生成空文件;文件不存在,清空原文件(ofstream打开方式)。如果没有文件,打开失败;如果有文件,定位到文件尾,但是不能写文件(ifstream打开方式)。
ios::app  = 0x08, //供写,文件不存在则创建,若文件已存在则在原文件内容后写入新的内容,指针位置总在最后
ios::trunc  = 0x10, //在读写前先将文件长度截断为0(默认)
ios::nocreate = 0x20, //文件不存在时产生错误,常和in或app联合使用
ios::noreplace = 0x40, //文件存在时产生错误,常和out联合使用
ios::binary = 0x80  //二进制格式文件


filebuf::openprot; //默认的兼容共享方式
filebuf::sh_none;  //独占,不共享
filebuf::sh_read;  //读共享
filebuf::sh_write; //写共享
以上方式仅旧版VC中支持,新版VC在share.h中为Win32项目定义了如下方式[1] 
_SH_DENYRW 0x10 /* deny read/write mode*/
_SH_DENYWR 0x20 /* deny write mode */
_SH_DENYRD 0x30 /* deny read mode */
_SH_DENYNO 0x40 /* deny none mode */
_SH_SECURE 0x80 /* secure mode */


fstream // 文件流
ifstream  // 输入文件流
ofstream  // 输出文件流




ifstream和ofstream都提供了成员函数来重定位文件定位指针(文件中下一个被读取或写入的字节号)
在ifstream中 这个成员函数为seekg("seek get");在ofstream中为seekp("seek put")
seekg(绝对位置); //绝对移动, //输入流操作
seekg(相对位置,参照位置);  //相对操作
tellg(); //返回当前指针位置
seekp(绝对位置); //绝对移动, //输出流操作
seekp(相对位置,参照位置);  //相对操作
tellp()和tellg()成员函数分别用来返回当前get和put的指针位置
参照位置:
ios::beg = 0  //相对于文件头
ios::cur = 1  //相对于当前位置
ios::end = 2  //相对于文件尾




1.读写文本文件的示例:
//为能够正确读出写入文件的各数据,各数据间最好要有分隔
#include<fstream>
void main()
{
fstream f("d:\\try.txt",ios::out);
f<<1234<<' '<<3.14<<'A'<<"How are you"; //写入数据
f.close();
f.open("d:\\try.txt",ios::in);
int i;
double d;
char c;
char s[20];
f>>i>>d>>c;  //读取数据
f.getline(s,20);
cout<<i<<endl; //显示各数据
cout<<d<<endl;
cout<<c<<endl;
cout<<s<<endl;
f.close();
}




2.创建一个文本文件并写入信息
//同向屏幕上输出信息一样将信息输出至文件
#include<iomanip>
#include<fstream>
void main()
{
ofstream f1("d:\\me.txt"); //打开文件用于写,若文件不存在就创建它
if(!f1)return; //打开文件失败则结束运行
f1<<setw(20)<<"姓名:"<<"张三"<<endl;  //使用插入运算符写文件内容
f1<<setw(20)<<"家庭地址:"<<"华盛顿"<<endl;
f1.close();  //关闭文件
}


3.使用get()一次读一个字节
#include<fstream>
void main()
{
ifstream fin("d:\\简介.txt",ios::nocreate);
if(!fin){
cout<<"File open error!\n";
return;
}
char c;
while((c=fin.get())!=EOF)cout<<c;  //注意结束条件的判断
fin.close();
}


4.使用get(char *,int n,char delim='\n')一次读多个字符
//巧妙利用文本文件中不会有字符'\0'的特点进行读取
#include<fstream>
void main()
{
ifstream fin("d:\\简介.txt",ios::nocreate);
if(!fin){
cout<<"File open error!\n";
return;
}
char c[80];
while(fin.get(c,80,'\0')!=NULL)cout<<c; //注意结束条件的判断
fin.close();
}


5.使用read(char *,int n)读文件
#include<fstream>
void main()
{
ifstream fin("d:\\简介.txt",ios::nocreate);
if(!fin){
cout<<"File open error!\n";
return;
}
char c[80];
while(!fin.eof())  //判断文件是否读结束
{
fin.read(c,80);
cout.write(c,fin.gcount());
}
fin.close();
}


6.文件的拷贝
//二进制文件操作示例
#include<fstream>
void main()
{
ifstream fin("C:\\1.exe",ios::nocreate|ios::binary);
if(!fin){
cout<<"File open error!\n";
return;
}
ofstream fout("C:\\2.exe",ios::binary);
char c[1024];
while(!fin.eof())
{
fin.read(c,1024);
fout.write(c,fin.gcount());
}
fin.close();
fout.close();
cout<<"Copy over!\n";


三、Win32文件读写
在Win32系统下文件可以支持平常的同步读写和异步读写(但在Win9X下,Win32系统不支持磁盘文件的异步读写)。本节在后面部分将会介绍文件的异步读写,最后一段内容将向大家讲解一下文
件的区域加锁。Win32系统中支持64位长度的文件,所以在很多文件操作函数中需要两个DWORD参数来表示文件长度,一个DWORD用来表示低32位,另一个用来表示高32位。文件的读写进行在文件
被正确打开后,但请确认在打开文件时设置了正确的读写标记。在Win32的文件操作中没有了以前类似与以前ANSI C中的fputs fgets fprintf fscanf等函数,只有类似于fread和fwrite的
ReadFile和WriteFile函数。


ReadFile用于文件读,函数原型为:


BOOL ReadFile(
  HANDLE hFile,                // handle to file
  LPVOID lpBuffer,             // data buffer
  DWORD nNumberOfBytesToRead,  // number of bytes to read
  LPDWORD lpNumberOfBytesRead, // number of bytes read
  LPOVERLAPPED lpOverlapped    // overlapped buffer
);
其中各项参数的含义为:
hFile:文件句柄,为CreateFile时返回的句柄
lpBuffer:保存读入的数据的指针
nNumberOfBytesToRead:指定需要读入的字节数
lpNumberOfBytesRead:返回实际读入的字节数
lpOverlapped:在文件异步读写时使用的数据,在同步读写中全部都设置为NULL,在Win9X中只支持对串口的异步操作。
如果返回值为FALSE并且读入的字节数也返回为0,则表示文件到达了末尾。
WriteFile用于文件写,函数原型为:
BOOL WriteFile(
  HANDLE hFile,                    // handle to file
  LPCVOID lpBuffer,                // data buffer
  DWORD nNumberOfBytesToWrite,     // number of bytes to write
  LPDWORD lpNumberOfBytesWritten,  // number of bytes written
  LPOVERLAPPED lpOverlapped        // overlapped buffer
);
参数的含义和ReadFile类似。
如果需要移动文件指针到相关位置(和文件读写不同,这个函数没有异步版本),使用


DWORD SetFilePointer(
  HANDLE hFile,                // handle to file
  LONG lDistanceToMove,        // bytes to move pointer
  PLONG lpDistanceToMoveHigh,  // bytes to move pointer
  DWORD dwMoveMethod           // starting point
);
其中各项参数的含义为:
hFile:文件句柄,为CreateFile时返回的句柄
lpBuffer:保存读入的数据的指针
lDistanceToMove:移动的字节数低DWORD
lpDistanceToMoveHigh:移动的字节数高DWORD,为了支持64位(2的64次方字节)长度的大文件,而用来指定64字节的高32位,如果文件大小只需要32位就可以表示,则设置为NULL
ldwMoveMethod:移动方法,可以选择下面的值。
FILE_BEGIN 从文件开始处开始移动
FILE_CURRENT 从文件开始除开始移动
FILE_END 从文件末尾开始移动


1.打开创建文件
HANDLE hFile = ::CreateFile(TEXT("E:\\CreateFileDemo.txt"),     //创建文件的名称。
    GENERIC_WRITE|GENERIC_READ,          // 写和读文件。
    0,                      // 不共享读写。
    NULL,                   // 缺省安全属性。
    CREATE_ALWAYS,          // 如果文件存在,也创建。
    FILE_ATTRIBUTE_NORMAL, // 一般的文件。       
    NULL);                 // 模板文件为空。
if (hFile == INVALID_HANDLE_VALUE) 

    OutputDebugString(TEXT("CreateFile fail!\r\n"));
}




2.写入文件
const int BUFSIZE = 4096;
char chBuffer[BUFSIZE];          
memcpy(chBuffer,"Test",4);
DWORD dwWritenSize = 0;
BOOL bRet = ::WriteFile(hFile,chBuffer,4,&dwWritenSize,NULL);
if (bRet)
{
    OutputDebugString(TEXT("WriteFile 写文件成功\r\n"));
}




3.读取文件


DWORD dwReadSize = 0;
::ZeroMemory(chBuffer,4096);
bRet = ::ReadFile(hFile,chBuffer,4,&dwReadSize,NULL);


if (bRet)
{
    OutputDebugString(TEXT("ReadFile 读文件成功\r\n"));
}
else
{
    //获取出错码。
    DWORD dwError = GetLastError(); 
    //处理出错。            
    TCHAR chErrorBuf[1024];
    wsprintf(chErrorBuf,TEXT("GetLastError()=%d\r\n"),dwError);
    OutputDebugString(chErrorBuf);
}




4.设置文件读写位置
LONG lDistance = 0;
DWORD dwPtr = SetFilePointer(hFile, lDistance, NULL, FILE_BEGIN);


SetEndOfFile函数,将当前文件位置设为文件末尾,GetFileSizeEx返回文件末尾大小
::SetEndOfFile(hFile);
LARGE_INTEGER liFileSize;
::GetFileSizeEx(hFile,&liFileSize);


四、MFC文件读写
MFC文件读写分为两种一种文件流读写,另外一种为文件映射
文件流读写:


1.CFile文件打开方式:


CFile::modeCreate


创建新文件,如果文件已存在,则将其长度变成0


CFile::modeNoTruncate


与modeCreate组合使用,如果文件已存在,则不会将其长度变成0


CFile::modeRead


以只读方式打开文件


CFile::modeReadWrite


以读写方式打开文件


CFile::modeWrite


以只写方式打开文件


CFile::modeNoInherit


组织该文件被子项继承


CFile::shareDenyNone


以共享模式打开文件,不会禁止其他进程对文件的读写


CFile::shareDenyRead


禁止其他进程对文件的读操作


CFile::shareDenyWrite


禁止其他进程对文件的写操作


CFile::shareExclusive


以独占模式打开文件,禁止其他进程对文件的读写


CFile::typeText


以文本方式打开文件


CFile::typeBinary


以二进制方式打开文件


2. CFile操作函数


函数


含义


Open


打开文件


Close


关闭文件


Flush


刷新待写的数据


Read


从当前位置读取数据


Write


向当前位置写入数据


GetLength


获取文件的大小


Seek


定位文件指针至指定位置


SeekToBegin


定位文件指针至文件头


SeekToEnd


定位文件指针至文件尾


GetFileName


获取文件名,如:“NOTEPAD.EXE”


GetFilePath


获取文件路径,如:“C:\WINDOWS \NOTEPAD.EXE”


GetFileTitle


获取文件标题,如:“NOTEPAD”


GetPosition


获取当前文件指针


GetStatus


获取当前文件的状态,返回一个CFileStatus


#Remove


静态方法,删除指定文件


#Rename


静态方法,重命名指定文件




写入文件:


CFile file;


file.Open("E:\\VC\\1.txt",CFile::modeCreate|CFile::modeWrite|CFile::modeNoTruncate,NULL);


file.Write("HelloWorld",strlen("121212aaaa"));  




file.close( );








读取文件:


CFile file;


file.Open("E:\\VC\\1.txt",CFile::modeRead,NULL); 


DWORD len=file.GetLength( );


char Buf[len+1];


Buf[len]=0;  //0终止字符串,用于输出。


file.Read(Buf,len);   //Read( void* lpBuf, UINT nCount ) lpBuf是用于接收读取到的数据的Buf指针nCount是从文件读取的字节数


MessageBox(Buf);




文件映射:
void main(int argc, char* argv[])
{
    // 创建文件对象(C: est.tsr)
    HANDLE hFile = CreateFile("C:/test.tsr", GENERIC_READ | GENERIC_WRITE,
        0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        printf("创建文件对象失败,错误代码:%d ", GetLastError());
        return;
    }
    // 创建文件映射对象
    HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
    if (hFileMap == NULL)
    {
        printf("创建文件映射对象失败,错误代码:%d ", GetLastError());
        return;
    }
    // 得到系统分配粒度
    SYSTEM_INFO SysInfo;
    GetSystemInfo(&SysInfo);
    DWORD dwGran = SysInfo.dwAllocationGranularity;
    // 得到文件尺寸
    DWORD dwFileSizeHigh;
    __int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
    qwFileSize |= (((__int64)dwFileSizeHigh) << 32);
    // 关闭文件对象
    CloseHandle(hFile);
    // 偏移地址 
    __int64 qwFileOffset = 0;
    // 块大小
    DWORD dwBlockBytes = 1000 * dwGran;
    if (qwFileSize < 1000 * dwGran)
        dwBlockBytes = (DWORD)qwFileSize;
    if (qwFileOffset >= 0)
    {
        // 映射视图
        TCHAR *lpbMapAddress = (TCHAR *)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS, 
            0, 0,
            dwBlockBytes);
        if (lpbMapAddress == NULL)
        {
            printf("映射文件映射失败,错误代码:%d ", GetLastError());
            return;
        }


        
//-----------------------访问数据开始-------------------------
        cout<<GetValue(lpbMapAddress,"SEU07201213")<<endl;
        getchar();
//-----------------------访问数据结束-------------------------        
    
        // 撤销文件映像
        UnmapViewOfFile(lpbMapAddress);
    }
    // 关闭文件映射对象句柄
    CloseHandle(hFileMap);    
}
string GetValue(const TCHAR *lpbMapAddress, const TCHAR *sName)
{
   string sValue;  // 存放 = 后面的value值
  TCHAR *p1 = NULL, *p2 = NULL; // 字符指针
  if((p1 = strstr(lpbMapAddress,sName)) != NULL) // 查找sName出现位置
  {
   if(p2 = strstr(p1,"/r/n")) *p2 = '/0'; // 查找"/r/n"(换行)出现位置
   sValue = p1+strlen(sName)+strlen("="); // 指针移动"sName"+"="之后
   *p2 = '/r';  // 还原*p2值,因为不还原会改变原文件结构
  }
  return sValue;
}
在处理一般的文件(文本/非文本),这些足够了。然而在处理比较大的文件如
几十M, 几百M, 甚至上G的文件, 这时再用一般手段处理,系统就显的力不从心了
要把文件读出,再写进,耗费的是CPU利用率与内存以及IO的频繁操作,
文件映射可以很好解决这个问题。

原创粉丝点击