C\C++\QT文件操作:流读写\内存映射

文章目录

  • 文件
    • 打开方式:文本 vs 二进制
  • C\C++文件操作
    • 常规(C)
    • 文件流(推荐)
      • 基本操作
        • fstream
        • 文本文件读写:流运算符
        • 二进制文件读写:ofstream::write() \ ifstream::read()
        • std::locale::global() 支持中文路径
        • 获取文件大小
        • 写入文件内容到结构体
        • 获取读取的字节数
      • 打开模式
      • 保护模式
    • 删除文件
  • QT文件操作
    • 基本读写操作
    • 流操作QTextStream\QDataStream
    • 文件内存映射
    • 文件对话框QFileDialog

文件

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

所谓“格式”,就是关于文件中每一部分的内容代表什么含义的一种约定。

  • 常见的纯文本文件(也叫文本文件,扩展名通常是“.txt”),指的是能够在 Windows 的“记事本”程序中打开,并且能看出是一段有意义的文字的文件。文本文件的格式可以用一句话来描述:文件中的每个字节都是一个可见字符的 ASCII 码
  • 除了纯文本文件外,图像、视频、可执行文件等一般被称作“二进制文件”。二进制文件如果用“记事本”程序打开,看到的是一片乱码。

打开方式:文本 vs 二进制

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

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

二进制方式打开 VS 普通打开:

  • 在 UNIX/Linux 平台中,用文本方式或二进制方式打开文件没有任何区别。以\n(ASCII 码为 0x0a)作为换行符号。
  • Windows换行符:两个字符\r\n(\r的 ASCII 码是 0x0d)。
    • Windows + 文本普通方式读取文件:系统会将文件中所有的\r\n转换成一个字符\n(0x0d0a =》系统丢弃前面的 0x0d 字节,只读入 0x0a)。而linux下会读入0D 0A两个字符。
    • Windows + 文本普通方式写入文件:系统会将写入的\n转换成\r\n存储(如果要写入的内容中有字节为 0x0a,则在写入该字节前,系统会自动先写入一个 0x0d)。

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

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

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

C\C++文件操作

常规(C)

文件流(推荐)

3 个文件流类:

  • ofstream:写文件
  • ifstream:读文件
  • fstream:读写文件
    C\C++\QT文件操作:流读写\内存映射_第1张图片

基本操作

fstream
文本文件读写:流运算符

>>:输入流运算符
<<:输出流运算符

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();
二进制文件读写: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 文件流关联
fs.write(chText, 30);  				//向test.txt文件中写入 url 字符串
fs.close();
std::locale::global() 支持中文路径

当传递NULL作为参数时,会调用local对象的一个显示默认构造函数,新构造出的对象包含当前系统的默认locale,随后的代码会比较当前本应用程序正在使用的locale是否和这个local对象所代表的locale一致,不一致的话则将这个local对象所携带的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(“”))的作用

获取文件大小

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),如何确定文件的大小?

写入文件内容到结构体
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读取结构体出错问题解决

获取读取的字节数
ifstream ifs("a.txt");
char buf[1024];
ifs.read(buf, 1024);
size_t extracted = ifs.gcount();

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

打开模式

C\C++\QT文件操作:流读写\内存映射_第2张图片

保护模式

#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进程不能再对文件进行读写。

C++文件操作
ofstream文件输出流把二进制数据写入文件

删除文件

int remove(const char * filename);

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)"));

你可能感兴趣的:(C++\QT,文件,流读写,内存映射)