文件

文件可分为文本文件、视频文件、音频文件、图像文件、可执行文件等多种类别(格式)。

纯文本文件(“.txt”):能够在 Windows 的“记事本”程序中打开,并且能看出是一段有意义的文字的文件。文件中的每个字节都是一个可见字符的 ASCII 码
图像、视频、可执行文件等:一般被称作“二进制文件”。二进制文件如果用“记事本”程序打开,看到的是一片乱码。

打开方式:文本 vs 二进制

std::ifstream in("file.txt", std::ios::binary);  

无论是否指定二进制方式打开文件,读写的最小单位都是字节

UNIX/Linux 平台:用文本方式或二进制方式打开文件没有任何区别。以\n(ASCII 码为 0x0a)作为换行符号。
Windows平台:默认换行符为两个字符\r\n(\r的 ASCII 码是 0x0d)。

  • Windows + 文本普通方式读取文件:系统会将文件中所有的\r\n转换成一个字符\n =》系统丢弃前面的 0x0d 字节,只读入 0x0a)。而linux下会读入0D 0A两个字符。
  • Windows + 文本普通方式写入文件:系统会将写入的\n转换成\r\n存储(如果要写入的内容中有字节为 0x0a,则在写入该字节前,系统会自动先写入一个 0x0d)。

=》因此,如果用文本方式打开二进制文件进行读写,读写的内容就可能和文件的内容有出入。因此,用二进制方式打开文件总是最保险的(更贴近原样)。

  • Windows + ios::binary方式写入:换行符存储为单字符。和Linux表现一致。
  • Windows + ios::binary读取:如果文件中本来存在0D 0A两个字符,windows 和 linux下均会读入0D 0A两个字符。

【C++】ios::binary是干嘛的?

C文件操作

FILE *fopen(const char *filename, const char *mode)
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

C++文件操作

fstream

3 个文件流类:

  • ofstream:写文件
  • ifstream:读文件
  • fstream:读写文件
    在这里插入图片描述
FILE *_fsopen(
   const char *filename,
   const char *mode,
   int shflag
);
FILE *_wfsopen(
   const wchar_t *filename,
   const wchar_t *mode,
   int shflag
);

文件打开模式:mode

ofstream
模式 备注
ios::app 如果没有文件,那么生成空文件;如果有文件,那么在文件尾追加。
ios::app | ios::in 不管有没有文件,都返回失败。
ios::ate 如果没有文件,那么生成空文件;如果有文件,那么清空该文件。
ios::ate | ios::in 如果没有文件,那么打开失败;如果有文件,那么定位到文件尾,并可以写文件,但是不能读文件。

ios::app方式打开文件,即使修改文件指针,也只能输出到文件尾,和文件指针无关。
ios::ate可以配合指针修改文件中的部分内容。

ifstream
模式 备注
ios::app (ios::app | ios::in) 不管有没有文件,打开都是失败。
ios::ate 如果没有文件,打开失败。如果有文件,打开成功,将清空原文件?
ios::ate | ios::in 如果没有文件,打开失败。如果有文件,打开成功,并定位到文件尾,但是不能写文件。
fstream

默认是ios::in

模式 备注
ios::app 如果没有文件,返回失败。
ios::ate 如果没有文件,返回失败。
ios::app | ios::out 如果没有文件则创建文件,如果有文件,则在文件尾追加。
ios::ate | ios::out 如果没有文件则创建文件,如果有,则清空文件。
ios::ate | ios::out | ios::in 如果没有文件,则打开失败,有文件则定位到文件尾。

在这里插入图片描述
ofstream之ios::ate,ios::app,ios::in,ios::out

共享类型\保护模式:shflag

#define _SH_DENYRW      0x10    /* deny read/write mode */拒绝对文件进行读写 
#define _SH_DENYWR      0x20    /* deny write mode */拒绝写入文件 
#define _SH_DENYRD      0x30    /* deny read mode */拒绝文件的读取权限 
#define _SH_DENYNO      0x40    /* deny none mode */读取和写入许可 
#define _SH_SECURE      0x80    /* secure mode */共享读取,独占写入 
//注意:假设A进程以_SH_DENYRW 打开,那么是B进程不能再对文件进行读写。
ofstream ofs;
ofs.open("./out.bin",ios::out| ios::app | ios::binary, _SH_DENYNO);  //允许第三方应用同时打开?

文件读写:文本模式

流运算符

>>:输入流运算符。以行为单位写入文件。
<<:输出流运算符。以空格、Tab、回车结束。

ifstream srcFile("in.txt", ios::in); 		//以文本模式打开in.txt备读
ofstream destFile("out.txt", ios::out); 	//以文本模式打开out.txt备写
if (!srcFile || !destFile) { 				//打开失败
    return;
}

while (srcFile >> x) {  					// 像用cin那样用ifstream对象
    destFile << x << " ";  					// 像cout那样使用 ofstream 对象
}
destFile.close();
srcFile.close();
getline()

以行为单位读入内存,能一次读入一行。碰到换行标志、EOF结束。

OpenFile.getline(str,20); 
get( ) & put()

一次读写一个字符。遇空白字符不停止读取。

char ch='1';
ofstream OpenFile("file.txt");   
OpenFile.put(ch);  
OpenFile.close();
char ch;  
ifstream OpenFile("file.txt");  
OpenFile.get(ch);  
cout<<ch;  
OpenFile.close();  

文件读写:二进制模式

ofstream::write() & ifstream::read()

打开文件:

const char *chText ="xxxxxx";
fstream fs("test.txt", ios::out | ios::binary);
fstream fs;  						//创建一个 fstream 类对象
fs.open("test.txt", ios::out);  	//将 test.txt 文件和 fs 文件流关联

文件是否打开成功:

if (!fs.is_open())
{
    fs.close();
}

写入:

fs.write(chText, 30);  					//向test.txt文件中写入 url 字符串

关闭:

fs.close();
写入文件内容到结构体
Student st;
fstream fs;
fs("test.txt",ios::out | ios::binary);//binary二进制输出
if(fs)
{
	fs.write(reinterpret_cast<char*>(&st), sizeof(st));
	//fs.write((char*)(&st),sizeof(st));
	fs.close();
}

Writing binary with ofstream.
利用fstream写入结构体(二进制写入)
C++ fstream读取结构体出错问题解决

文件是否打开成功:is_open()

if (!fs.is_open())
{
    fs.close();
}

缓存和同步

当缓存被排放出来(flush)时,它里面的所有数据或者被写入物理媒质中(如果是一个输出流的话),或者简单的被抹掉(如果是一个输入流的话)。这个过程称为同步(synchronization),它会在以下任一情况下发生:

  1. 当文件被关闭时。
  2. 当缓存buffer满时:缓存Buffers 有一定的空间限制。当缓存满时,它会被自动同步。
  3. 控制符明确指明:当遇到流中某些特定的控制符时,同步会发生。这些控制符包括:flush() 和endl。
  4. 明确调用函数sync():调用成员函数sync() (无参数)可以引发立即同步。这个函数返回一个int 值,等于-1 表示流没有联系的缓存或操作失败。

获取文件大小

ifstream:seekg + tellg
ifstream fsRead;
fsRead.open(srcFilePath.c_str(), ios::in|ios::binary);
if (!fsRead) {
    return;
}
fsRead.seekg(0, fsRead.end);  // 搜索到文件末尾
size_t srcSize = fsRead.tellg();  // 文件大小
if (!srcSize) {
    fsRead.close();
}
fsRead.seekg(0, 0);  // 还原到文件开头
ofstream:seekp + tellp
ofstream fsWrite;
fsWrite.open(destFilePath.c_str(), ios::out|ios::binary);
if (!fsWrite) {
    fsRead.close();
    return;
}
fsWrite.seekp(0, fsWrite.end);  // 搜索到文件末尾
size_t dstFileSize = fsWrite.tellp();  // 文件大小

seekg 和 seekp 的参数通常是一个长整型。第二个参数可以用于指定查找方向:
ios::beg:默认,从流的开头开始定位。
ios::cur:从流的当前位置开始定位。
ios::end:从流的末尾开始定位。

fileObject.seekg( n );  // 定位到 fileObject 的第 n 个字节(默认ios::beg)
fileObject.seekg( n, ios::cur );  // 把文件的读指针从 fileObject 当前位置向后移 n 个字节
fileObject.seekg( n, ios::end );  // 把文件的读指针从 fileObject 末尾往回移 n 个字节
fileObject.seekg( 0, ios::end );  // 定位到 fileObject 的末尾

fstream 获取文件大小_c++获取文件大小
使用C++文件流(fstream),如何确定文件的大小?

获取读取的字节数

ifstream ifs("a.txt");
char buf[1024];
ifs.read(buf, 1024);
size_t extracted = ifs.gcount();

std::ifstream::readsome和std::ifstream::read的区别

std::locale::global() 支持中文路径

当传递NULL作为参数时,会调用local对象的一个显示默认构造函数。
新构造出的对象包含当前系统的默认locale。
随后会比较当前本应用程序正在使用的locale是否和这个local对象所代表的locale一致,不一致的话则将这个local对象所携带的locale设置为新的locale(系统默认locale),并返回之前正在使用的locale。

ofstream ofs;  //打开文件用于写,若文件不存在就创建它
locale loc = locale::global(locale(""));  //要打开的文件路径含中文,设置全局locale为本地环境 
ofs.open("./out.bin",ios::out| ios::app | ios::binary, _SH_DENYNO); //输出到文件,追加、二进制
locale::global(loc);  //恢复全局locale

//写入文件
if (!ofs.is_open()) 
    return;
char* buffer = "fdsfdsfdsfdsfdsfds\n";
ofs.write(buffer, sizeof(char)*17); 
ofs.flush();
Sleep(1000);

ofs.close(); 

文件操作std::locale::global(std::locale(“”))的作用

状态标志符

bad()

如果在读写过程中出错,返回 true 。例如:当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候。

fail()

除了与bad() 同样的情况下会返回 true 以外,加上格式错误时也返回true ,例如当想要读入一个整数,而获得了一个字母的时候。

ofstream OpenFile("file.txt");
if (OpenFile.fail())  
{  
    cout<<"打开文件错误!"<<endl;  
    exit(0);  
}
eof()

如果读文件到达文件末尾,返回true。

while (!OpenFile.eof())  
{  
    //文件结束时的代码  
}
good()

这是最通用的:如果调用以上任何一个函数返回true 的话,此函数返回 false 。

C++文件操作
ofstream文件输出流把二进制数据写入文件
C/C++读写文件的几种方法fstream fopen、fwrite()、fread()操作

删除文件

int remove(const char * filename);

_finddata_t存储文件信息

头文件#include <io.h>


struct _finddata_t
{
     unsigned attrib;
     time_t time_create;
     time_t time_access;
     time_t time_write;
     _fsize_t size;
     char name[_MAX_FNAME];
};

_finddata_t结构体用法

QT文件操作

基本读写操作

QFile file(fileName); // fileName文件的路径
if(file.open(QIODevice::ReadOnly | QIODevice::Text))  // 以读写的方式打开文件
	return ;
while (!file.atEnd()) {
	QByteArray line = file.readLine();
}

流操作QTextStream\QDataStream

QFile file("in.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    return;
QTextStream in(&file);
while (!in.atEnd()) {
    QString line = in.readLine();
}

QFile Class

文件内存映射

uchar *QFileDevice::map(qint64 offset, qint64 size, QFileDevice::MemoryMapFlags flags = NoOptions)

偏移量开始将文件的大小字节映射到内存(虚拟内存)中。应该打开一个文件以使映射成功,换句话说就是映射必须打开一个文件,但在映射内存之后,该文件不需要保持打开状态。当QFile被销毁或用这个对象打开一个新文件时,任何未被映射的映射都将被自动取消映射。

在处理数据量较大的文件时,往往需要使用文件映射技术,即虚拟内存。 通过文件映射之后,就可以像操作内存一样去直接操作文件。而不需要再调用文件读写方法了。
给磁盘上的文件分配地址,类似内存的地址一样,对虚拟出来的内存的操作就是对文件的操作了。

qt的内存映射

Qt——文件映射

文件对话框QFileDialog

QString strFileName = QFileDialog::getOpenFileName(this, tr("Open Image"), "/home/", tr("Image Files (*.png *.jpg *.bmp)"));
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐