目录
1.你真的理解文件原理和操作了吗? 不是语言问题,是系统问题
2.是不是只有C/C++有文件操作呢? 不是,Java,python,go都有,他们的文件操作方法是不一样的?如何处理这种现象呢? 有没有一种统一的视角,看待所有的语言文件从操作呢?
3.操作文件的时候,第一件事情,就是打开文件,打开文件时做什么呢?如何理解呢?
4. 文件 = 内容 + 属性 -> 针对文件的操作,对内容的操作,对属性的操作
5.当文件没有被操作的时候,文件一般会 在什么位置? 磁盘!
6.当我们对文件进行操作的时候, 文件需要在哪里? 内存,为什么呢? 因为 CPU和内存交互
7.当我们对文件进行操作的时候,文件需要提前被load到内存,load是 内容还是属性? 属性,因为一个文件至少得有属性
8.当我们对文件进行操作的时候,文件需要提前被load到内存,是不是只有你一个人在load呢?不是, 内存中一定存在大量的不同文件的属性
9.所以综上, 打开文件本质就是将需要的文件属性加载到内存中,OS内部一定会同时存在大量的被打开的文件,那么操作系统要不要管理这些被打开的文件呢? 要, OS需要先描述,在组织。
先描述,构建在内存中的文件结构体struct file{struct file* next},就可以从磁盘来,被打开的文件
a.每一个被打开的文件,都要在OS内对应文件对象的struct结构体,可以将所有的struct file结构体用某种数据结构链接起来--,在OS内部,对被打开的文件进行管理,就被转换成为了对链表的增删查改。
结论:文件被打开,OS要为被打开的文件,创建对应的内核数据结构
struct file
{
//各种属性
//各种链接关系
}
10.文件其实可以被分开两大类: 磁盘文件,被打开的文件( 内存文件)
11.文件被打开,是谁打开呢?OS,但是是谁让OS打开的呢?用户(进程为代表的)
12.我们之前的所有的文件操作,都是进程和被打开文件的关系
13.都是进程和被打开文件的关系: struct stak_struct和 struct file
下面是用C语言实现对文件log.txt进行操作:
#include <stdio.h>
#define LOG "log.txt"
int main()
{
// w:默认写方式打开文件,如果文件不存在,就创建它
// 默认如果只是打开,文件内容会自动被清空
// 同时,每次进行写入的时候,都会从最开始进行写入
FILE *fp = fopen(LOG, "w");
if (fp == NULL)
{
perror("fopen fail");
return 1;
}
// 正常进行文件操作
const char *msg = "hello linux\n";
int cnt = 5;
while (cnt)
{
fputs(msg, fp);
cnt--;
}
fclose(fp); // 关闭文件
return 0;
}


成功创建了log.txt文件,打开文件


printf 默认是向显示器读取
int main()
{
// w:默认写方式打开文件,如果文件不存在,就创建它
// 1. 默认如果只是打开,文件内容会自动被清空
// 2. 同时,每次进行写入的时候,都会从最开始进行写入
FILE *fp = fopen(LOG, "w");
if (fp == NULL)
{
perror("fopen fail");
return 1;
}
// 正常进行文件操作
const char *msg = "hello linux";
int cnt = 5;
while (cnt)
{
fprintf(fp, "%s:%d:phw\n", msg, cnt);
cnt--;
}
fclose(fp); // 关闭文件
return 0;
}

fprintf(stdout, "%s:%d:phw\n", msg, cnt); // Linux一切皆文件,stdout也对应一个文件,显示器文件

写入到buffer缓冲里


下面测试一下将msg改成phw


这里得出结论, “w"为覆盖式写入
追加式写入"a"选项






pathname: 要打开或创建的目标文件
flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。
参数:
O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写O_TRUNC:清空文件内容
返回值:
成功:新打开的文件描述符
失败:-1
下面是标志位的举例程序:
#define ONE 0x1
#define TWO 0x2
#define THREE 0x4
#define FOUR 0X8
#define FIVE 0X10
void Print(int flags)
{
if (flags & ONE)
printf("hello 1\n");
if (flags & TWO)
printf("hello 2\n");
if (flags & THREE)
printf("hello 3\n");
if (flags & FOUR)
printf("hello 4\n");
if (flags & FIVE)
printf("hello 5\n");
}
int main()
{
printf("-------------------\n");
printf(ONE);
printf("-------------------\n");
printf(TWO);
printf("-------------------\n");
printf(FOUR);
printf("-------------------\n");
printf(ONE | TWO);
printf("-------------------\n");
printf(ONE|TWO|THREE);
printf("-------------------\n");
printf(ONE|TWO|THREE|FOUR|FIVE);
printf("-------------------\n");
return 0;
}


open函数测试:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define LOG "log2/txt"
// 系统方案
int main()
{
int fd = open(LOG, O_WRONLY);
printf("fd:%d\n", fd);
return 0;
}

文件不存在
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#define LOG "log2/txt"
// 系统方案
int main()
{
int fd = open(LOG, O_WRONLY |O_CREAT);
if (fd == -1)
{
printf("fd:%d,errno:%d,errstring:%s\n", fd, errno, strerror(errno));
}
else
{
printf("fd:%d,errno:%d,errstring:%s\n", fd, errno, strerror(errno));
}
close(fd);
return 0;
}
我们在使用open函数的时候不仅要O_WRONLY (写)还要创建O_CREAT
但是这种方式创建的文件,是没有权限的。

其中参数mode就是权限


因为umask默认权限的原因
umask() 函数的参数为一个八进制数,它的每一位分别表示对应的文件权限是否会被屏蔽掉,例如,umask(022) 表示屏蔽掉写入权限和执行权限。
umask(0)这意味着没有任何权限被屏蔽掉。

将mask初始化为0


成功将文件的权限设置成自己想要的


这里的strlen不需要+1,\0是C语言的规定,不是文件的规定,\0会被解释成乱码

O_WRONLY | O_CREAT 默认不会对原始文件内容做清空,需要加上O_TRUNC

O_APPEND | O_CREAT 不会追加写,需要加上O_WRONLY

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define LOG "log.txt"
// 系统方案
int main()
{
umask(0);
int fd = open(LOG, O_RDONLY, 0666);
if (fd == -1)
{
printf("fd:%d,errno:%d,errstring:%s\n", fd, errno, strerror(errno));
}
else
{
printf("fd:%d,errno:%d,errstring:%s\n", fd, errno, strerror(errno));
}
char buffer[1024];
// 这里无法做到按行读取,我们是整体读取的
ssize_t n = read(fd, buffer, sizeof(buffer) - 1); //使用系统接口来进行IO的时候,一定要注意\0的问题
if (n > 0)
{
buffer[n] = '\0';
printf("%s\n", buffer);
}
close(fd);
return 0;
}

在认识返回值之前,先来认识一下两个概念: 系统调用和库函数
上面的 fopen fclose fread fwrite 都是C标准库当中的函数,我们称之为库函数(libc)。
而, open close read write lseek 都属于系统提供的接口,称之为系统调用接口
回忆一下我们讲操作系统概念时,画的一张图

系统调用接口和库函数的关系,一目了然。 所以,可以认为,f系列的函数,都是对系统调用的封装,方便二次开发。
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
Ⅰ软件测试基础一、软件测试基础理论1、软件测试的必要性所有的产品或者服务上线都需要测试2、测试的发展过程3、什么是软件测试找bug,发现缺陷4、测试的定义使用人工或自动的手段来运行或者测试某个系统的过程。目的在于检测它是否满足规定的需求。弄清预期结果和实际结果的差别。5、测试的目的以最小的人力、物力和时间找出软件中潜在的错误和缺陷6、测试的原则28原则:20%的主要功能要重点测(eg:支付宝的支付功能,其他功能都是次要的)80%的错误存在于20%的代码中7、测试标准8、测试的基本要求功能测试性能测试安全性测试兼容性测试易用性测试外观界面测试可靠性测试二、质量模型衡量一个优秀软件的维度①功能性功
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc