文件操作总结

文章目录

  • 前言
  • 文件操作—C语言
  • 文件操作—C++
  • 文件操作—WIN32


前言

最近因为用到了文件操作相关内容,所以趁着机会总结一下。这里主要介绍三种文件操作的方法,分别是C语言、C++以及WIN32里的文件操作方法。

所谓"文件",一般指存储在外部介质上数据的几何,一般数据都是以文件的形式存放在外部介质上的,而我们的操作系统是以文件为单位对数据进行管理的。

对文件进行分类,依据不同,分出的类别也不同。按介质可将文件分为:磁盘文件、光盘文件、U盘文件;按用途可将文件分为:程序文件(program file)、数据文件(data file);按文件中数据的组织形式可将文件分为:文件文件(以ascll表示文本文件,.txt .cpp .c)、二进制文件(用二进制表示文件 .o .exe .mp3 .bmp .png .jpg)。


文件操作—C语言

c语言的文件操作:

    1.头文件:stdio.h
    2.文件是一个结构:FILE
    3.文件指针:FILE* fp; //指向一个文件的指针
    4.文件内部"指针":抽象的东西 “光标”
    5.文件结束的标志:EOF
 
打开文件

  FILE *fopen(char *filename,char * Mode);
  以Mode方式打开filename文件,返回一个文件指针。

    文本文档
     r   只读   只能读取里面的内容 不能写!
    w   只写   不管你打开的文件里面有什么,直接清空,可以写入数据
     a   追加   文件的后面写入
    r+   读写   可以读取数据,写入,从内部指针开始覆盖
    w+   读写   清空文件,写读
    a+   读写   可以读可以写,文件的后面写入

    二进制文档
     rb   只读   只能读取里面的内容 不能写!
    wb   只写   不管你打开的文件里面有什么,直接清空,可以写入数据
     ab   追加   文件的后面写入
    rb+   读写   可以读取数据,写入,从内部指针开始覆盖
    wb+   读写   清空文件,写读
    ab+   读写   可以读可以写,文件的后面写入

文件打开失败的几种原因:
    1.只读r r+的方式去打开一个不存在的文件
    2.要打开的文件路径盘符不符合
    3.文件名非法
    4.文件被别的程序占用

关闭文件

    fclose(fp)
    不关闭文件,有可能导致数据丢失

读和写

   fscanf   向文件格式化写入   fscanf(fp, “%d\t%s\t%f\n”, &pnew->num, pnew->name, &pnew->math)
  fprintf  向文件格式化读取  fprintf(fp, “%d\t%s\t%f\n”, pStu->num, pStu->name, pStu->math);
  fgetc  读一个字符串  char fgets(char str,int size,FILEfp);
  fputc  写入一个字符串  int fputs(char
str,FILE*fp);
  fread  从文件fp读取数据 每一次读取size个字符 读取count次 保存在str,不会补充’\0’  size_t fread(void * str, size_t size, size_t count, FILE *fp);
  fwrite  把str往分配写入,一次写入size个 写入count次  size_t fwrite(void * _Str, size_t Size, size_t Count,FILE *File);
  fseek  移动文件内部指针  fseek(fp,offset,flag) fp 文件 offset 偏移量 flag 0头部 1当前位置 2文件尾
  ftell  返回当前的内部指针相对于文件头的偏移量  int ftell(fp);
  rewind  把文件内部指针直接移动到开头  rewind(fp);
  fflush  清除读写缓冲区  int fflush(FILE *stream)

例子

// FILE.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include
#include
#include
#include

struct Camera
{
	//Camera(void);

	double focal_length = 0.0;
	double distortion[2];
	double translation[3];
	double rotation[9];
	bool is_constant = false;
};

struct Point3D
{
	double pos[3];
	bool is_constant = false;
};

struct Observation
{
	double pos[2];
	int camera_id;
	int point_id;
};

std::vector<Camera> cameras;
std::vector<Point3D> points;
std::vector<Observation> observations;
	
void OpenFile(const char *filename,std::vector<Camera>& cams, std::vector<Point3D>& pts3D, std::vector<Observation>& observations)
{
	FILE *fp;

	if ((fp = fopen(filename, "r")) == NULL) //不存在
	{
		printf("\t\t\t文件不存在!");
		return;
	}

	char line[15];
	//加载相机参数
	{
		int n_cams;
		fscanf(fp, "%s\t%d", line, &n_cams);
		fgetc(fp);
		cams.resize(n_cams);
		for (int i = 0; i < cams.size(); i++)
		{
			fscanf(fp, "%lf", &cams[i].focal_length);
			fscanf(fp, "%lf\t%lf", &cams[i].distortion[0], &cams[i].distortion[1]);
			
			for (int j = 0; j < 3; j++)
				fscanf(fp, "%lf\t", &cams[i].translation[j]);
			
			for (int j = 0; j < 9; j++)
			{
				if (j == 8)
					fscanf(fp, "%lf\n", &cams[i].rotation[j]);

				else
					fscanf(fp, "%lf\t", &cams[i].rotation[j]);
			}

		}
	}

	// 加载三维点
	{
		int n_points;
		fscanf(fp, "%s\t%d\n", line, &n_points);
		pts3D.resize(n_points);
		for (int i = 0; i < n_points; i++) 
			fscanf(fp, "%lf\t%lf\t%lf\n", &pts3D[i].pos[0], &pts3D[i].pos[1], &pts3D[i].pos[2]);
	}

	//加载观察点
	{
		int n_observations;
		fscanf(fp, "%s\t%d\n", line, &n_observations);
		observations.resize(n_observations);
		for (int i = 0; i < observations.size(); i++) 
			fscanf(fp, "%lf\t%lf\t%lf\t%lf\n", &observations[i].camera_id, &observations[i].point_id, &observations[i].pos[0], &observations[i].pos[1]);
	}
}
int main()
{
	OpenFile("test_ba.txt", cameras, points, observations);

	return 0;
}


文件操作—C++

文件流

  文件流是以外村文件为输入输出对象的数据流,每一个文件流都有一个内存缓冲区与之对应。其中输出文件流是从内存流向外村文件的数据,输入文件流是从外村文件流向内存的数据。
  文件流本身不是文件,是以文件为输入输出对象的流,要对磁盘文件输入输出,必须通过文件流实现,即文件操作需要流对象,cout、cin是已定义的流对象。
文件操作总结_第1张图片

文件流类

  在C++的I/O类库中专门用于文件操作的类
  要对文件输入输出,必须定义一个文件流类的对象
  C++是通过流对象进行输入输出的,在用标准设备为对象的输入输出中,cin,cout是流对象。文件操作也是要定义流对象,例:ofstream outfile;

文本文件的读写

1) 打开磁盘文件
  打开文件是指在文件读写之前做必要的准备工作:(1)为文件流对象和指定的磁盘文件建立关联,以便使文件流流向指定的磁盘文件;(2)指定文件的工作方式
  打开文件的两种不同方法:(1)调用文件流的成员函数open,如ofstream outfile; outfile.open(“f1.dat”,ios::out); (2)在定义文件流对象时调用文件流类的构造函数,istream infile(“f1.dat”,ios::in);

2) 打开文件的方式
  ios::in:供读,文件不存在时,打开失败(ifstream默认的打开方式)
  ios::out:供写,文件不存在则创建,若文件存在,则清空原内容(ofstream默认的打开方式)
  ios::ate:文件打开时,指针在文件最后;可改变指针的位置,常和in、out联合使用
  ios::app:供写,文件不存在则创建,若文件已存在,则在原文件内容后添加写入新的内容
  ios::trunc:在读写前先将文件长度截断为0(默认)
  ios::nocreate:文件不存在时产生错误,常和in或app联合使用
  ios::noreplace:文件存在时产生错误,常和out联合使用
  ios::binary:二进制格式文件

3) 关闭文件
  在对已打开的磁盘文件的读写操作完成后,应关闭该文件。
   outfile.close(); //关闭磁盘文件"f1.dat"
  关闭文件,将缓冲区中的数据妥善处理,解除了磁盘文件与文件流的关联,不再通过文件流对该文件进行输入或输出。

4) 文本文件的读写
  文本文件,或称ASCII文件:文件中的每一个字节均以ASCII代码形式存放,即一个字节存放一个字符。
  程序可以从文本文件中读入若干个字符,也可以向它输出一些字符。
  对ASCII文件的读写操作的方法: (1)用流插入运算符“<<”和流提取运算符“>>”输入输出标准类型的数据。 (2)用文件流的put, get, geiline等成员函数进行字符的输入输出。

二进制文件的读写

1)对于数值数据的存储方式
  short int a = 12345; //2个字节

  文本形式:直观便于人阅读,占用内存较多,需要转换。
  ‘0’ 00110000
  ‘9’ 00111001
   ‘1’        ‘2’      ‘3’      ‘4’     ‘5’
  00110001 00110010 00110011 00110100 00110101
  二进制形式:计算机的内部形式,节省空间。不需要转换,但是不直观。
   12345
  00110000 00111001

2)读写二进制文件
   打开方式
     ofstream a(“file1.dat”, ios::out | ios::binary);
     ifstream b(“file2.dat”,ios::in | ios::binary);
   文件读写方式
    istream& read(char *buffer,int len);
    ostream& write(const char * buffer,int len);
     char *buffer 指向内存中一段存储空间 
    int len 是读写的字节数 
   例:
    a.write(p1,50) 将p1指向的空间中50个字节存入文件对象a
    b.read(p2,30) 从文件对象b读出30个字节,存之指向空间

文件指针的成员函数
文件操作总结_第2张图片

例子
要读的文件如下:
文件操作总结_第3张图片

// FILE_C++.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include 
#include
#include
#include
#include
#include

struct Camera
{
	//Camera(void);

	double focal_length = 0.0;
	double distortion[2];
	double translation[3];
	double rotation[9];
	bool is_constant = false;
};

struct Point3D
{
	double pos[3];
	bool is_constant = false;
};

struct Observation
{
	double pos[2];
	int camera_id;
	int point_id;
};

std::vector<Camera> cameras;
std::vector<Point3D> points;
std::vector<Observation> observations;

void load_data(const std::string& file_name, std::vector<Camera>& cams, std::vector<Point3D>& pts3D, std::vector<Observation>& observations)
{
	/* 加载数据 */
	std::ifstream in(file_name);
	assert(in.is_open());
	std::string line, word;

	//加载相机参数
	{
		int n_cams = 0;
		getline(in, line);
		std::stringstream stream(line);
		stream >> word >> n_cams;
		cams.resize(n_cams);
		for (int i = 0; i < cams.size(); i++)
		{
			getline(in, line);
			std::stringstream stream(line);
			stream >> cams[i].focal_length;
			stream >> cams[i].distortion[0] >> cams[i].distortion[1];
			for (int j = 0; j < 3; j++)
				stream >> cams[i].translation[j];
			for (int j = 0; j < 9; j++)
				stream >> cams[i].rotation[j];
		}
	}

	// 加载三维点
	{
		int n_points = 0;
		getline(in, line);
		std::stringstream stream(line);
		stream >> word >> n_points;
		pts3D.resize(n_points);
		for (int i = 0; i < n_points; i++) {
			getline(in, line);
			std::stringstream stream(line);
			stream >> pts3D[i].pos[0] >> pts3D[i].pos[1] >> pts3D[i].pos[2];
		}
	}

	//加载观察点
	{
		int n_observations = 0;
		getline(in, line);
		std::stringstream stream(line);
		stream >> word >> n_observations;
		observations.resize(n_observations);
		for (int i = 0; i < observations.size(); i++) {
			getline(in, line);
			std::stringstream stream(line);
			stream >> observations[i].camera_id
				>> observations[i].point_id
				>> observations[i].pos[0]
				>> observations[i].pos[1];
		}
	}
}

int main()
{
	load_data("../data/test_ba.txt", cameras, points, observations);

	return 0;
}

文件操作—WIN32

创建或打开Windows文件

HANDLE WINAPI CreateFile(
  _In_      LPCTSTR lpFileName,				//文件名
  _In_      DWORD dwDesiredAccess,          //访问权限
  _In_      DWORD dwShareMode,				//共享模式
  _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,  //安全属性
  _In_      DWORD dwCreationDisposition,    //文件创建模式
  _In_      DWORD dwFlagsAndAttributes,     //文件属性
  _In_opt_  HANDLE hTemplateFile			//文件模板
);

读写数据

写数据

BOOL WriteFile(
  HANDLE hFile,                       //文件句柄          
  LPCVOID lpBuffer,                   //数据BUFF
  DWORD nNumberOfBytesToWrite,        //数据长度
  LPDWORD lpNumberOfBytesWritten,     //返回实际写入的数据
  LPOVERLAPPED lpOverlapped           //默认为NULL
);

读数据

BOOL ReadFile(
  HANDLE hFile,                   //文件句柄
  LPVOID lpBuffer,                //数据BUFF
  DWORD nNumberOfBytesToRead,     //要读的字节数
  LPDWORD lpNumberOfBytesRead,    //实际读到字节数
  LPOVERLAPPED lpOverlapped       //默认为NULL
);

关闭文件

BOOL CloseHandle(
  HANDLE hObject      //文件句柄
);

相关函数

获取本机存在的驱动器

DWORD GetLogicalDrives(VOID);

获取系统盘的盘符

DWORD GetLogicalDriveStrings( 
DWORD nBufferLength,   //缓冲区大小
LPTSTR lpBuffer        //接受数据的缓冲区
 );

获取盘符类型

UINT GetDriveType( LPCTSTR lpRootPathName   //盘符根目录
);
返回值:
DRIVE_UNKNOWN - 驱动器类型不能确定。
DRIVE_NO_ROOT_DIR - 根目录不存在。
DRIVE_REMOVABLE - 可移动磁盘。
DRIVE_FIXED - 本地磁盘
DRIVE_REMOTE - 远程(网络)驱动器。
DRIVE_CDROM - CD-ROM驱动器。
DRIVE RAMDISK - RAM磁盘。

获取程序当前工作目录

DWORD GetCurrentDirectory(
    DWORD nBufferLength,    //缓冲区大小 
    LPTSTR lpBuffer         //接受数据的缓冲区
);

设置程序当前工作目录

BOOL SetCurrentDirectory(
    LPCTSTR lpPathName     //要设置的目录名
);

获取Windows目录

UINT GetWindowsDirectory(
    LPTSTR lpBuffer,     //接受数据的缓冲区
    UINT uSize           //缓冲区大小    
);

获取Windows的System目录

UINT GetSystemDirectory(
    LPTSTR lpBuffer,     //接受数据的缓冲区       
    UINT uSize           //缓冲区大小            
);

获取临时文件目录

DWORD GetTempPath(
    DWORD nBufferLength,  //接受数据的缓冲区
    LPTSTR lpBuffer       //缓冲区大小   
);  

创建目录

BOOL CreateDirectory(
    LPCTSTR lpPathName,   //目录名称
    LPSECURITY_ATTRIBUTES lpSecurityAttributes   //安全属性,默认为NULL 
);

删除目录

BOOL RemoveDirectory(
    LPCTSTR lpPathName    //目录名称(目录中不能包含子目录或文件)
);

移动目录

BOOL MoveFile(
    LPCTSTR lpExistingFileName,     //已存在的目录
    LPCTSTR lpNewFileName           //新的路径(不能跨盘移动)
);

获取文件长度

DWORD GetFileSize(
  HANDLE hFile,  //文件句柄
  LPDWORD lpFileSizeHigh  
); 

文件指针

DWORD SetFilePointer(
  HANDLE hFile,              //文件句柄
  LONG lDistanceToMove,      //偏移量的低32位
  PLONG lpDistanceToMoveHigh, //偏移量的高32位
  DWORD dwMoveMethod          //偏移的相对位置
); 

拷贝文件

BOOL CopyFile(
LPCTSTR lpExistingFileName, //源文件名
LPCTSTR lpNewFileName,      //目标文件名
BOOL bFailIfExists          //如果设为TRUE(非零),那么一旦目标文件已经存在,则函数调用会失败。否则目标文件被改写
);

删除文件

BOOL DeleteFile(
LPCSTRlpFileName     //要删除的文件名的指针
);

移动文件

BOOL MoveFile(
  LPCTSTR lpExistingFileName,  //一个存在的文件或者文件夹字符串指针
  LPCTSTR lpNewFileName        //个还没存在的文件或者文件夹的字符串指针
);

获取文件属性

DWORD WINAPI GetFileAttributes(
  __in LPCTSTR lpFileName  //文件或目录的名字,对于ANSI版本,名字不能大于MAX_PATH(260)
);

设置文件属性

BOOL SetFileAttributes(
  LPCTSTR lpFileName,    //要设置其属性的文件名
  DWORD dwFileAttributes //文件属性
);

获取文件属性、时间等

BOOL GetFileAttributesEx(
  LPCTSTR lpFileName,	//指向指定文件或目录的字符串的指针
  GET_FILEEX_INFO_LEVELS fInfoLevelId,	//指定要获取的属性信息的类型的值
  LPVOID lpFileInformation	//指向缓冲区的指针,以接收属性信息
);	 

查找文件

 HANDLE FindFirstFile(
      LPCTSTR lpFileName,    //查找路径
      LPWIN32_FIND_DATA lpFindFileData  //查找的数据  
    );  

获取下一个文件

BOOL FindNextFile(
      HANDLE hFindFile,   //查找句柄
      LPWIN32_FIND_DATA lpFindFileData  //查找的数据
    ); 

关闭查找

BOOL FindClose(
  HANDLE hFindFile     //查找句柄
);

例子

// FILE_WIN32.cpp : 文件打开读写。
//
#include
#include
int main(int argc, char *argv[])
{
	HANDLE handle = CreateFile(L"../data/abc.dat", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
		OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

	if (handle == INVALID_HANDLE_VALUE)
	{
		printf("打开文件失败!%d\n", GetLastError());
		return -1;
	}

	//写文件
	DWORD realWrittenBytes = 0;
	BOOL ret = WriteFile(handle, "hello,world", strlen("hello,world"), &realWrittenBytes, 0);

	if (ret == 0)
	{
		printf("写入文件失败!%d\n", GetLastError());
		return -1;
	}

	//追加数据
	SetFilePointer(handle, 0, 0, FILE_END);
	WriteFile(handle, "你好,世界", strlen("你好,世界"),&realWrittenBytes, 0);

	//获取文件的大小
	DWORD loSize = 0, hiSize = 0;
	loSize = GetFileSize(handle, &hiSize);
	printf("low Size = %d, High Size = %d\n", loSize, hiSize);

	//关闭文件句柄
	CloseHandle(handle);

	return 0;
}
//遍历查找文件

#include 
#include
void findFile(char* pathName);

//遍历目录
int main(int argc, char* argv[])
{
	char curPath[MAX_PATH] = { 0 };
	GetCurrentDirectory(MAX_PATH, (LPSTR)curPath);
	printf("%s", &curPath);
	findFile(curPath);
	return 0;
}

bool isDotOrDotdot(char* pathName)
{
	if (strcmp(pathName, ".") == 0 ||
		strcmp(pathName, "..") == 0)
		return true;

	return false;
}

void findFile(char* pathName)
{
	char fileFileName[_MAX_PATH] = { 0 };
	sprintf_s(fileFileName, "%s\\*", pathName);  //查找当前目录下的所有文件

	WIN32_FIND_DATA findData;
	
	HANDLE handle = FindFirstFile(fileFileName, &findData);  //尝试找第一个文件
	if (handle == INVALID_HANDLE_VALUE)
	{
		printf("没有文件\n");
		return;
	}
	
	BOOL bFind = TRUE;
	char szTemp[MAX_PATH] = { 0 };
	while (bFind)
	{
		if (findData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
		{
			if (!isDotOrDotdot(findData.cFileName))
			{				
				sprintf_s(szTemp, "%s\\%s", pathName, findData.cFileName);
				printf("文件夹 : %s\n", szTemp);
				findFile(szTemp);
			}			
		}
		else
		{
			memset(szTemp, 0x00, MAX_PATH);
			sprintf_s(szTemp, "%s\\%s\n", pathName, findData.cFileName);
			printf("fileName : %s", szTemp);
		}

		//继续查找下一个文件,如果找不到,则返回FALSE
		bFind = FindNextFile(handle, &findData);  
	}
}

你可能感兴趣的:(#,C++,#,WIN32,编程语言)