当前位置: 首页 > news >正文

cpp文件操作

文件操作

数据流

在cpp中,流(stream)是一个抽象概念,用于描述如何从一个位置到又一个位置传输数据。流主要用于I/O操作。

数据流包括两大类:1. 输入流(istream):数据从某个源流入程序, 2. 输出流(ostream):数据从程序流向某个目的地。

根据操作对象不同分为文件流、字符串流、控制台流。

控制台流

控制台流(<iostream>)主要用于标准输入输出操作的一部分。这些流提供了一个接口,用于与用于进行交互,即从键盘读取和向屏幕输出,无论程序在那种操作系统或平台上运行。

iostream:同时包括istreamosteam,是一种多继承的关系,在程序应用中可以只包含头文件<iostream>

常见对象有:cin(标准输入),cout(标准输出),cerr(用于显示错误信息)。

<<>>运算符,是ostream类使用友元函数的方式对各种基本数据类型重载了<<操作符,使我们能够方便地将数据输出到流中。

文件流

文件流主要包括输入文件流<ifstream>输出文件流<ofstream>输入输出文件流<fstream>,这些类都定义在<fstream>头文件中。

与标准输入输出流cincout不同,文件流需要指定具体的文件来操作。因此,我们需要创建一个流对象并为其指定一个文件名和其他相关属性。

ofstream类的默认构造函数原形为:

ofstream::ofstream(const char *filename, int mode = ios::out, int pmode = filebuf::openprot);

其中filmname表示指定要打开的文件名。

mode是一个标志位,用于指定如何打开文件。默认值是ios::out,意味着文件以输出模式打开

pmode是一个与平台相关的权限参数,指定了文件的权限。

类型解释
ios::app输出追加模式。当写入文件时,数据会被追加到文件的末尾,而不是覆盖文件的内容。
ios::ate初始位置在文件的末尾,但你可以移动到文件中的任何位置进行读写操作。
ios::binary文件以二进制模式打开。不使用这个模式时,默认为文本模式。
ios::in文件以输入模式打开(通常与 ifstream 一起使用)。
ios::out文件以输出模式打开(默认值)。
ios::trunc如果文件已存在,其内容将被截断或删除。
ios:nocreate不建立文件,所以文件不存在时打开失败
ios:.noreplace不覆盖文件,打开文件时如果文件存在失败

打开文件属性值

类型解释
0普通文件,打开访问
1只读文件
2隐含文件
4系统文件

“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。  文件使用完后可以使用close成员函数关闭文件。

ios::app,当你用这种模式打开文件时,先检查文件的状态。例如,你可以使用 file.is_open() 来确定文件是否成功打开,以及使用 file.fail() 来检查是否有任何I/O错误。这有助于确保文件操作的安全和有效。

字符串流

字符串流定义在<sstream>头文件中,主要有以下三种类型的字符串流:

  1. istringstream: 输入字符串流,允许从一个 std::string 对象中读取。
  2. ostringstream: 输出字符串流,允许写入到一个 std::string 对象。
  3. stringstream: 同时支持读写操作的字符串流。

文件处理

C++的文件处理也可以看作为一个对象,使用文件流的类,使用头文件<fstream>,处理的时候有文本文件二进制文件之分,主要的区别就是存储的形式。

文件处理可以概括成如下几个过程:

  1. 包含头文件
  2. 创建文件流对象
  3. 打开文件
  4. 文件读写
  5. 关闭文件
打开文件

打开文件的核心:打开文件涉及到通知操作系统你希望访问文件的特定部分(例如读、写或两者兼而有之),并且通常会得到一个文件句柄或文件描述符,该描述符后续可用于读写操作。

下面是open()函数的标准语法,open()ifstreamofstreamfstream类的成员函数,用于打开文件。

void open(const char *filename, ios::openmode mode = ios::in | ios::out);

open() 成员函数的第一参数指定要打开的文件的名称和位置,第二个参数定义文件被打开的模式。

image-20231010153854667

以上的不同模式标志,可以组合使用为文件指定复杂的打开行为。

例如:

  • 写入模式与截断模式
ofstream outf;
outf.open("file.txt", ios::out | ios::trunc);

ios::trunc:当与ios::out一起使用时,这个标志表示如果文件已经存在,则其内容应被截断或清空。如果不指定这个标志并且文件已存在,写入操作通常会覆盖文件的现有内容,从文件的开头开始。

  • 读写模式
fstream file;
file.open("file.txt", ios::out | ios::in);

结合ios::inios::out,意味着你可以对文件进行读写操作。当使用这种模式打开文件时,现有的文件内容不会被自动截断或清空。你可以在文件中任意地移动,进行读和写操作。

文件的写入与输出
  1. 写入文件

在cpp中,可以使用流插入运算符(<<)将数据写入文件,类似于将信息输出到控制台的方式。

对比控制台输出和文件输出:

std::cout << "Hello, World!";

这是cout代表标准输出的ostream类实例。

std::ofstream outFile("filename.txt");
outFile << "Hello, File!";

outFileofstream 类的实例。 ofstream 代表“输出文件流”,允许将数据写入文件。

  1. 读取文件

从文件读取涉及流提取运算符 ( >> ),类似于从键盘获取输入。唯一不同的是,在这里使用的是 ifstream 或 fstream 对象,而不是 cin 对象。

  1. 关闭文件

在cpp程序终止时,他会自动关闭并且刷新所有流,释放所有分配的内存,并关闭所有打开的文件,但显示关闭文件是一个好习惯。

使用完文件后关闭文件的原因如下

  • To make sure that all buffered data gets written.确保所有缓冲数据都被写入。
  • To release the resources associated with the file.释放与该文件关联的资源。
  • To prevent any potential data corruption.防止任何潜在的数据损坏。

下面是close()函数的标准语法,close() 函数是 fstream、ifstream 和ofstream 对象的一个成员。

void close()

文件写入简单示例:

#include<iostream>
#include<fstream>
using namespace std;int main(){// 创建流对象ofstream outf;// 打开文件outf.open("file.txt", ios:: app);// 写入数据outf << "Hello World" << endl;// 关闭文件outf.close();return 0;
}

文件读取的简单示例:

#include<iostream>
#include<fstream> //文件流的头文件
using namespace std;
int main()
{char a;ifstream infile; //定义ifstream类(输入文件流类)对象outfileinfile.open("file.txt");//打开文件 使文件流与c++.txt文件建立关联while (!infile.eof()){infile.get(a); //依次获取文件中每个字符 并输出cout << a;}infile.close(); //关闭文件 使文件流与c++.txt文件断开关联
}

这种方法效率低,不建议使用。

第二种方法:

char buf[1024] = {0};
while (ifs >> buf) {cout << buf << endl;
}

第三种:

char buf[1024] = {0};
while (ifs.getline(buf, sizeof(buf))) {cout << buf << endl;
}

第四种:

string buf;
while (getline(ifs, buf)) {cout << buf << endl;
}
ifs.close();
二进制文件读写

二进制写文件主要利用流对象调用成员函数write(),这个函数直接从内存中的某个位置(由buffer指针指定)写入指定的字节数(len)到文件中。

函数原型:ostream& write(const char*buffer,int len);

#include<iostream>
#include<fstream> //文件流的头文件
using namespace std;
class Student {
public:Student() {}Student(string name,int age) :name(name), age(age) {}
protected:string name;int age;
};
int main() {ofstream bof;Student s1("张三", 100);bof.open("student.txt", ios::out|ios::binary);bof.write((const char*) & s1, sizeof(Student));bof.close();return 0;
}

读取文件用read 函数从文件中读取指定的字节数并将其放入指定的内存位置。

ifstream bif;bif.open("student.txt", ios::in | ios::binary);if (!bif.is_open()) {cout << "文件打开失败" << endl;return 0;}Student s2;bif.read((char*)&s2, sizeof(Student));cout << s2.name << " " << s2.age << endl;bif.close();

fstream文件操作

打开文件和关闭文件

打开文件fstream可以在生命流对象时传入文件名打开文件,也可以使用open()函数打开文件。

文件打开后必须关闭,fstream提供了close()函数关闭文件。

打开文件

使用构造函数声明对象时打开文件:

fstream ioFile("data.txt", ios::in | ios::out);

使用open()函数打开文件:

fstream file;
file.open("example.txt", ios::in | ios::out);

如果只传文件名,系统会自动根据文件类型选择默认的打开方式。

  • ios::in:读取模式
  • ios::out:写入模式
  • ios::app:追加模式。数据会被写入文件的末尾而不是覆盖已有内容。
  • ios::trunc:如果文件存在,则先删除文件的内容,然后再打开它。
  • ios::binary:以二进制模式打开文件。

模式和属性可以单独使用,也可以混合使用。在混合使用时,需要使用逻辑连接符或|链接。

ios::out会默认清空文件,即ios::out|ios::trunc打开文件的同时清空文件。如果不想清空文件,那么设置读写模式为ios::out|ios::app,以这种模式打开文件后,是以追加内容的方式写入文件。

fstream提供了多种读写操作,包括:

  • <<>>:这些操作符用于向文件写入数据和从文件读取数据。
  • read()write():这些函数用于处理二进制文件。
  • put()get():这些函数分别用于写入和读取单个字符。
  • getline():这个函数用于从文件中读取一行文本。

示例:

读取文本文件:

ifstream file("example.txt");
string line;
while(getline(file, line)) {cout << line << endl;
}
file.close();

读取二进制文件:

ifstream file("binaryExample.bin", ios::binary);
int number;
file.read((char*)&number, sizeof(number));
file.close();
  • 文本文件:这些文件主要包含文本,如.txt。你通常会使用逐行读取/写入的方式来处理它们。
  • 二进制文件:这些文件包含二进制数据,如图像、音频或编译后的程序。当处理这些文件时,你会使用块读写的方式,这意味着你可能会一次读取/写入多个字节。

完整示例:

#include <iostream>
#include <fstream>  // 1. 包含头文件
#include <string>
using namespace std;int main() {string str;fstream iofile;  // 2. 创建对象// 3. 打开文件并清空内容iofile.open("file.txt", ios::out | ios::in | ios::trunc);// 4. 写入数据iofile << "这里是写入内容测试" << endl;iofile << "this is test" << endl;iofile.close();  // 5. 关闭文件cout << "写入完毕" << endl;// 重新打开文件进行读取iofile.open("file.txt", ios::out | ios::in);while (getline(iofile, str))  // 循环读取{cout << str << endl;}iofile.close();cout << "读取完毕" << endl;return 0;
}

二进制数据读写文件:

#include <iostream>
#include <fstream>
using namespace std;int main() {int numbers[] = {10, 20, 30, 40, 50};fstream iofile;// 1. 打开文件以进行二进制写入iofile.open("binaryfile.bin", ios::out | ios::binary | ios::trunc);iofile.write((char*) &numbers, sizeof(numbers));iofile.close();cout << "数据已写入二进制文件" << endl;int readNumbers[5] = {0};// 2. 打开文件以进行二进制读取iofile.open("binaryfile.bin", ios::in | ios::binary);iofile.read((char*) &readNumbers, sizeof(readNumbers));iofile.close();cout << "从二进制文件读取的数据:" << endl;for(int i = 0; i < 5; i++) {cout << readNumbers[i] << " ";}cout << endl;return 0;
}

文件定义与大小

当你在处理文件时,经常需要控制文件的读写位置或查询其大小。C++提供了一组非常强大的工具来实现这一目的,下面将详细介绍这些功能及其用法。

文件定位:seekg() 和 seekp()

seekg()seekp() 分别用于设置输入和输出流的位置。

  • seekg():设置输入流的位置(对应读操作)。
  • seekp():设置输出流的位置(对应写操作)。

这些函数需要两个参数:

  • offset:这是从给定起点移动的字节量。它可以是正数(向前移动)或负数(向后移动)。
  • origin:这定义了从哪里开始计算偏移。常用的起点有:
    • ios::beg:从文件开始处。
    • ios::cur:从文件的当前位置。
    • ios::end:从文件的末尾。
示例:
fstream file("example.txt", ios::in | ios::out);// 将读指针从文件开始处向后移动2个字节
file.seekg(2, ios::beg);// 将写指针从当前位置向后移动2个字节
file.seekp(2, ios::cur);
2. 获取文件大小:tellg() 和 tellp()

这两个函数返回当前的读或写位置,通常表示为从文件开始到当前位置的字节数。

  • tellg():获取输入流的当前位置。
  • tellp():获取输出流的当前位置。

如果你想知道整个文件的大小,一个常见的方法是将读指针移动到文件的末尾,然后使用 tellg()

示例:
fstream file("example.txt", ios::in | ios::out);// 将读指针移动到文件末尾
file.seekg(0, ios::end);// 获取当前位置,即文件大小
streampos size = file.tellg();
cout << "文件大小是: " << size << " 字节" << endl;
注意:
  • 在操作完成后,可能需要将文件指针重新定位到适当的位置,以便进行后续的读/写操作。
  • 尝试读取超出文件大小的位置可能会导致未定义的行为,通常是读取失败。

相关文章:

cpp文件操作

文件操作 数据流 在cpp中&#xff0c;流&#xff08;stream&#xff09;是一个抽象概念&#xff0c;用于描述如何从一个位置到又一个位置传输数据。流主要用于I/O操作。 数据流包括两大类&#xff1a;1. 输入流(istream)&#xff1a;数据从某个源流入程序, 2. 输出流(ostrea…...

failed to req API:/nacos/v1/ns/instance after all servers([localhost:8848])

仔细观察我的Nacos日志后发现是Nacos没启动起来,足足花费了30分钟才启动, 应该是电脑卡机导致的,之前电脑启动Nacos很快的!!只要启动了Nacos服务就可以解决该报错! 后续: 后面是选择这个CMD里面一些内容复制,然后右键粘贴到里面好像是能刷新这个CMD的内容,然后就启动成功了...

【ROS】ros-noetic和anaconda联合使用

【ROS】ros-noetic和anaconda联合使用 文章目录 【ROS】ros-noetic和anaconda联合使用1. 安装anaconda2. 创建虚拟环境3. 查看python解释器路径4. 在虚拟环境中使用任意的包5. 创建工作空间和ros功能包进行测试Reference 1. 安装anaconda 在Ubuntu20.04中安装anaconda可以参考…...

【MySQL】聚合查询与分组查询

我们先重建一个test库&#xff0c;在test库里新建一个people表&#xff08;包含序列号&#xff0c;姓名&#xff0c;工资&#xff09;&#xff0c;再往表该表里新增六条数据&#xff1a; mysql> drop database if exists test; Query OK, 1 row affected (0.07 sec)mysql>…...

RFID技术在锂电池生产线自动化应用

随着电动汽车和能源储存系统市场的不断扩大&#xff0c;锂离子电池作为其核心部件&#xff0c;以其高能量密度、长寿命等优点成为了主流选择。而对于锂电池智能化、高效化生产有着更高的要求&#xff0c;RFID技术的使用&#xff0c;将大幅度提高锂电池的生产产能&#xff0c;从…...

钢筋智能测径仪 光圆与带肋钢筋均可检测!

在一个大规模、高效、连续的工业生产中&#xff0c;制造业正朝着自动化方向快速优化发展&#xff0c;这种自动化的生产需要快速、准确地分析控制生产工艺中的参数&#xff0c;超差及时提示&#xff0c;为操作工对工厂的运行和自我调节做出快速反应&#xff0c;人工操作越来越不…...

docker--在Anaconda jupyter 容器中使用oracle数据源时,Oracle客户端安装配置及使用示例

配置oracle 11.2 客户端 将instantclient-basic-linux.x64-11.2.0.4.0.zip解压至/home/jupyter/oracle/将instantclient-sqlplus-linux.x64-11.2.0.4.0.zip解压/home/jupyter/oracle/【可选&#xff0c;提供sqlplus命令】复制【操作系统一般都有安装libaio.so】 cp /usr/lib64…...

can的波特率/比特率

can控制器只需要进行少量的设置就可以进行通信&#xff0c;就像RS232那样。其中较难设置的部分就是通信波特率的计算。can总线能够在一定范围内容忍总线上can节点的通信波特率的偏差&#xff0c;这种技能使得can总线有很强的容错性&#xff0c;同时也降低了对每个节点的振荡器精…...

项目经理涨薪秘籍!技巧都在这里了

好奇前辈们是如何带好团队、做出成功项目&#xff0c;从而升职加薪&#xff0c;成为高级项目经理或项目管理主管的&#xff1f;这是绝大多数新手PM最关注的事情。今天小编给大家揭秘&#xff01; 一、刚入门如何进阶 从入门的项目管理者发展到中级的项目管理者&#xff0c;重…...

甘特图组件DHTMLX Gantt示例 - 如何有效管理团队工作时间?(一)

如果没有有效的时间管理工具&#xff0c;如工作时间日历&#xff0c;很难想象一个项目如何成功运转。这就是为什么我们的开发团队非常重视项目管理&#xff0c;并提供了多种选择来安排DHTMLX Gantt的工作时间。使用DHTMLX Gantt这个JavaScript库&#xff0c;您可以创建一个强大…...

健效达海豚妈妈儿保项目推介会盛大启幕,聚焦互联网+精准医疗

2023年10月12日&#xff0c;由上海健启星科技发展有限公司和北京安智因生物技术有限公司联合主办的“2023互联网精准医学平台助力基层医疗|海豚妈妈儿保项目推介会”在中国苏州盛大启幕。 本次项目推介会得到国内行业专家、权威学者、国内知名三甲名医教授、头部企业、学术大咖…...

使用XLua在Unity中获取lua全局变量和函数

1、Lua脚本 入口脚本 print("OK") --也会执行重定向 require("Test") 测试脚本 print("TestScript") testNum 1 testBool true testFloat 1.2 testStr "123"function testFun()print("无参无返回") endfunction te…...

springboot项目集成kafka,并创建kafka生成消息线程池

效果图: 步骤1:添加依赖 <!-- kafka依赖 --><dependency><groupId>org.apache.kafka</groupId><<...

PreScan与MATLAB联合仿真报错

一、 问题&#xff1a; Error:Matlab ||和&&运算符的操作数必须能够转换为逻辑标量值 二、解决办法 必须安装VS2013&#xff08;我装的VS2017不行的&#xff09;&#xff0c;然后重启prescan和MATLAB&#xff0c;编译通过&#xff0c;界面如下&#xff1a; 三、VS…...

ros学习笔记(1)Mac本地安装虚拟机,安装Ros2环境

Ros与Linux的关系 Ros环境基于Linux系统内核 我们平时用的是Linux发行版&#xff0c;centos&#xff0c;ubuntu等等&#xff0c;机器人就用了ubunut 有时候我们经常会听到ubunue的版本&#xff0c;众多版本中&#xff0c;有一些是长期维护版TLS&#xff0c;有一些是短期维护…...

史上最强,Jmeter性能测试-性能场景设计实例(详全)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、性能测试需求 …...

【vim 学习系列文章 7-- vim vnormap nnoremap nmap map inoremap 区别】

文章目录 1.1 vim 递归映射和非递归映射1.1.1 vim 可视模式 1.2 map nmap vnormap nnoremap inoremap 区别 1.1 vim 递归映射和非递归映射 递归映射和非递归映射是 Vim 中两种不同的键盘映射方式。 递归映射&#xff08;recursive map&#xff09;是指在定义键盘映射时&#x…...

[ERROR] COLLATION ‘utf8_unicode_ci‘ is not valid for CHARACTER SET ‘latin1‘

[ERROR] COLLATION utf8_unicode_ci is not valid for CHARACTER SET latin1错误来源是&#xff1a; 跟着b站的谷粒商城项目做&#xff0c;前面的视频中设置了数据库的字符集编码&#xff0c;但是后面自己发现了MySQL容器重启报错&#xff0c;不停的在重启 查看log信息可以使用…...

基于rancher安装部署k8s

基础配置 systemctl stop firewalld && systemctl disable firewalld setenforce 0 sed -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/configvi /etc/hosts ip1 node1 ip2 node2 ip3 node3#免密登录 ssh-keygenssh-copy-id -i ~/.ssh/id_rsa.pub 普通用户ip1…...

保姆级微服务部署教程

大家好&#xff0c;我是鱼皮。 项目上线是每位学编程同学必须掌握的基本技能。之前我已经给大家分享过很多种上线单体项目的方法了&#xff0c;今天再出一期微服务项目的部署教程&#xff0c;用一种最简单的方法&#xff0c;带大家轻松部署微服务项目。 开始之前&#xff0c;…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...