? ? ? ? 在linux下操作一个文件,首先要保证文件的存在(不存在就创建),接着打开文件(打开成功)并得到文件描述符,接着在进行读写操作,最后还需要关闭文件。如果我们对文件进行读写之后不关闭文件,而直接关闭我们的编译器,可能会造成文件损坏。
? ? ? ? ?文件描述符其实就是我们使用open函数后一个返回值,我们一般用fd表示。如果你成功的打开文件,open就会返回一个非负值,我们让fd等于这个非负值;如果你打开文件失败,open就会返回-1,那么fd就被赋值为-1。
? ? ? ? ?如果说我们的文件夹是一本书,文件是书本的章节,那么文件描述符就相当于我们书本的索引(就是一个目录,标示了你想要找的东西的位置)。当你想要读写文件的内容时,你需要利用相应的API函数,而这些API函数的其中一个参数就是文件描述符。API函数通过“文件描述符”这个索引就可以找到文件并对该文件进行操作。
Ctrl Alt t | 开启命令窗口 |
xrandr | 显示所有的分辨率 |
xrandr -s 分辨率 | 设置自己想要的分辨率 |
Ctrl l | 清屏 |
Ctrl shift +或者Ctrl + | 放大文字 |
Ctrl - | 缩小文字 |
pwd | 显示当前文件路径 |
ls | 显示当前路径下有哪些文件(不包含隐藏文件) |
ls -a | 显示当前路径下有哪些文件(包含隐藏文件) |
ls -l | 显示当前路径下文件的创建时间大小及用户使用权限 |
mkdir 文件夹名 | 创建文件夹 |
rm -r 文件夹名 | 删除文件夹 |
rm 文件名 | 删除文件 |
cd 文件夹名 | 进入文件夹 |
cd .. | 返回上一级目录 |
mv *c 新文件夹名 | 把当前目录下名字以c结尾的文件或文件夹剪切到新文件夹里 |
mv 文件名1 文件名2 | 把文件1的名字命名为文件2 |
mv 文件夹名1 文件夹名2 | 把文件夹1的名字命名为文件夹2 |
cp 文件1 文件2 | 把文件1的内容复制到文件2 |
cp -r 文件夹1 文件夹2 | 把文件夹1的内容复制到文件夹2 |
vi 文件名.c | 创建.c文件,进入后默认为命令行模式,按i进入输入模式;按Esc由输入模式进入命令模式。接着输入:wq回车,保存退出。 |
gcc 文件名.c | 编译该.c文件,默认生成名为a.out的可运行文件 |
./a.out | 运行a.out文件 |
gcc 文件名.c -o 新文件名 | 编译该.c文件,生成以新文件命名的可运行文件 |
./新文件名 | 运行新文件名的文件 |
vim -r 文件名 | 打开上一次奔溃的文件 |
vimdiff 文件名1 文件名2 | 在同一显示屏下比较两个文件,并显示不同的部分 |
clear | 清屏 |
ps -aux | 查看所有进程 |
cat 已有文件名 | 查看文件内容 |
cat > 新文件名 | 创建新文件,可以再文件里写入内容,按ctrl c退出 |
ps -aux|grep 类型名 | 查看这一类型的进程 |
top | 查看任务管理器 |
getpid | 获取自身进程id号 |
getppid | 获取父进程id号 |
1.创建/打开文件
①int open(const char *pathname, int flags);
②int open(const char *pathname, int flags, mode_t mode);
③int creat(const char *pathname, mode_t mode);
参数
Pathname:要打开的文件名字(包含路径,缺失为当前路径)
Flags:
必须要有的选项,三选一
O_RDONLY 只读打开 ??O_WRONLY 只写打开 ??O_RDWR可读可写打开
备用常用选项,可用“|”叠加
O_CREAT:若文件不存在则创建该文件。使用后,要搭配第三个参数mode,以此来说明该新文件的存取许可权限。
O_EXCL:如果同时指定了O_CREAT,并且文件已经存在则打开文件失败,返回-1。
O_APPEND:每次书写都加到文章末尾
O_TRUNC:如果该文件已经存在,并且是一个常规文件,并且访问模式允许写入(即,是O_RDWR或O_WRONLY)它将被截断为长度0。
Mode:在flag中使用了O_CREAT标志后,可以使用该参数设置待创建文件的访问权限
关于mode的参数补充
每个Linux文件具有四种访问权限:可读(r)、可写(w)、可执行(x)和无权限(-)。
利用ls -l命令可以看到某个文件或目录的权限,它以显示数据的第一个字段为准。第一个字段由10个字符组成,如 -rwxr-xr-x,我们把它划分为4部分
第1位为第一部分,表示文件类型,-表示文件,d表示目录
第2-4位为第二部分,表示文件所有者的权限,u权限
第5-7位为第三部分,表示文件所有者所属组成员的权限,g权限
第8-10位为第四部分,表示所有者所属组之外的用户的权限,o权限 ?
2-10位的权限总和有时称为a权限
以上例子中,表示这是一个文件(非目录),文件所有者具有读、写和执行的权限,所有者所属组成员和所属组之外的用户具有读和执行的权限而没有写的权限。
如果我们使用int open(const char *pathname, int flags, mode_t mode)函数,参数mode是数字,那我们如何用数字表示第二第三第四部分的权限呢?
所谓数字表示法,是指将r、w和x分别用4、2、1来代表,没有授予权限的(即-)则为0,
比如我们刚刚举得例子rwxr-xr-x,它的2到10位一共三个部分的权限,我们划分来看。
第二部分是rwx,对应数字是421,加起来就是7;第三部分是r-x,对应数字是401,加起来就是5;第四部分是rwx,对应数字是401,加起来就是5。所以如果mode用数字表示就是755,具体的例子,下面的程序再说。
如果打开成功,返回新的文件描述符(一个非负整数),如果发生错误,一般返回-1。
①与②API函数的区别在有无mode,而需不需要mode这个参数,就要看第二个参数里是否包含O_CREAT。如果有O_CREAT,就要包含mode这个参数;如果没有,就不用包含这个参数。因为如果包含O_CREAT同时文件没有,那么文件就需要被创建,被创建的同时还需要规定文件的访问权限,这就需要mode的参与。
③这个API函数可以直接去输入你想要的文件名,以及权限,就可以实现文件的创建了
2.写入文件
④ssize_t write(int fd, const void *buf, size_t count);
参数:
fd:文件打开后对应的文件描述符
buf:写入内容缓冲区
count:写入文件的大小
如果写入成功,则返回写入的字节数。如果出现错误,则返回-1,并设置errno以指示错误的原因。
3.读文件
⑤ssize_t read(int fd, void *buf, size_t count);
参数:
fd:文件打开后对应的文件描述符
buf:读内容缓冲区
count:读入文件的大小
如果写入成功,则返回读的字节数。如果出现错误,则返回-1,并设置errno以指示错误的原因。
4.文件光标移动
⑥off_t lseek(int fd, off_t offset, int whence);
参数:
fd:文件打开后对应的文件描述符
offset:相对于whence偏移的位置。0,不偏移;正整数,向右偏移对应的大小;负整数,向左偏移对应的大小。
whence:光标起始位置,一共有三个选项,如下
SEET_SET???????? 文件开头
SEET_CUR???????? 文件当前位置
SEET_END???????? 文件尾部
如果成功,则返回相对于文件头的偏移量。如果出现错误,则返回-1。如果我们设置为
lseek(fd,0,SEET_END)就可以利用他的返回值来表示文件的大小了。
5.关闭文件
⑦int close(int fd);
参数
fd:文件打开后对应的文件描述符
关闭成功返回零。如果出现错误,则返回-1,并适当地设置errno。
1.文件创建的验证
?? 在当前目录下,我们是没有file1文件的,这时候我们建立demo1.c,使用int open(const char *pathname, int flags)无法打开file1。如下图
当前文件下无file1
demo1.c的代码
执行完demo1.c,文件描述符fd的返回值是-1,说明打开文件失败
建立demo2.c使用int open(const char *pathname, int flags, mode_t mode),先进行判断,如果没有file1,显示失败时的文件描述符,接着建立file1后在显示正确的文件描述符;如果有file1,直接显示正确的文件描述符。
demo2.c代码,
执行完demo2.c后的情况,可以看到file1从无到有,通过O_CREAT实现了file1的创建,最后的文件描述符为正值。
当前路径下输入ls -l可以查看当前路径下所有文件的权限以及状态。在demo2.c里我们将open函数的第三个参数mode设置为0600,可以看到对应的file1是对应的权限是
-rw-------,结合我们上文讲的数字表示文件权限就可以知道0600就代表者第二部分拥有可读可写的权限
2.文件写入验证
首先我们删除file1,在demo3.c里使用write函数,写入yangdong is handsome
demo3.c的代码如下
执行完demo3.c后结果如下图所示
打开file1后可以看到文件显示的内容
3.文件读取的验证
在demo3.c的基础上修该代码,首先我们要通过文件描述符的值验证file1中是否写成功入了内容。当成功写入后,我们要调用lseek()函数把文件光标置前,不然我们读取内容的时候是从文件的末尾读取的,但是你可以想象,既然文件光标都到文章末尾了,都没东西了,那你还读啥?读空气啊。所以当你往文章里写好东西之后,如果你想要读,记得把文件光标置前。
我们依旧先删除file1,在demo4.c里使用write,lseek,read函数,写入yangdong is handsome
demo4.c的代码如下
执行完demo4.c后的现象,我们可以看到写入多少,读出多少;写入什么,读出什么。
4.open函数打开文件中参数flag中可搭配选项的验证
O_EXCL功能的验证
file1此时已存在,我们可以看到demo5.c的open函数中同时加入了O_CREAT和O_EXCL,这时候文件打开失败,文件描述符被赋值为-1。
demo5.c的代码
demo5.c的运行结果
O_APPEND的验证
现在file1里面的内容是yangdong is handsome,如果想在文件中继续写入123456。但是我们在open函数里不加参数O_APPEND和加O_APPEND有啥区别呢,下面我们来看一下。
open函数里不加O_APPEND
原文件内容如下
代码如下
运行完之后file1的内容如下
我们可以看到,不过open函数里不加O_APPEND,那么我们写入文件的内容就会写入多少,覆盖原文件多少。
现在在现有file1的基础上验证open函数里加O_APPEND的情况
原文件内容如下
代码如下
运行结果如下,我们可以看到open函数里加O_APPEND后,写入的内容是从文件末尾新加进去,并没有覆盖原文件内容
验证O_TRUNC:
现在file1的内容如下
当我们在open函数中加入参数O_TRUNC以后,我们往文件中写入内容,原文件的内容会被全部删除,只显示我们新写入的东西。
代码如下
运行后file1中的内容如下,可以看到原来的内容已经被替换成了abcdefg