linux文件与重定向
目录
一、共识原理
二、回顾C语言文件函数
1.fopen
2.fwrite
3.fclose
三、文件系统调用
1.open
2.write
3.访问文件的本质
4.stdin&&stdout&&stderror
5.文件的引用计数
四、重定向
1.文件描述符的分配规则
2. 输出重定向
3.重定向系统调用
4.追加重定向
5.输入重定向
6.1号VS2号
一、共识原理
1.文件=内容 + 属性
我们关注文件,不仅要关注它的内容,也要关心它的属性,一个文件即使没有内容,它的大小也不是空的,因为该文件的属性也是会占用空间的。
2.文件分为打开的文件和没打开的文件
3.打开的文件
谁在打开文件?我们在代码中写一个fopen,fwrite,最终都会变成进程,因此是进程在打开文件。
研究打开的文件---本质是研究进程和文件的关系!文件被打开,必须被加载到内存!内容和属性都被加载到内存。
进程:打开的文件 = 1 : n。一个进程是可以打开多个文件的,因此进程和打开的文件关系是1:n的
操作系统内部,一定存在大量的被打开的文件!OS要不要管理这些打开的文件呢?-怎么管理???-先描述在组织,在内核中,一个被打开的文件都必须有自己的文件打开对象,包含文件的很多属性。
4.没打开的文件:在哪里放着呢?在磁盘上。我们最关注什么问题?没有被打开的文件非常多,我怎么找到我要打开的文件?因此文件必须被分门别类的归置好---方便我们快速的进行增删查改---快速找到文件。
二、回顾C语言文件函数
1.fopen
fopen的第一个参数是文件名,如果不带路径,默认就在当前路径下打开,如果带了绝对路径,就在绝对路径下打开,第二个参数是以什么方式打开,是读呢?还是写呢?还是追加写?下面我们打开了"log.txt"这个文件,在当前路径下是没有log.txt这个文件的,fopen如果打开不存在的文件会新建在打开,是以读方式打开。果然在我们的当前路径下创建了一个log.txt文件。
下面的问题是,当前路径,什么是当前路径呢?当前路径就是进程的当前路径,如果我们把进程的当前路径修改了,是不是就可以把文件新建到其它目录下呢?那怎么修改进程的当前路径呢?chdir。
可以看到,当把 进程的当前工作目录修改了之后,创建的文件log.txt的路径也随之发生了变化。
2.fwrite
fwrite的第一个参数是写入内容的起始地址,第二个参数是写多少个,第三个是当做一个几部分写入,第四个是要写入那个文件里。
这里我们直接把message当做一个整体写入到fp里,也就是log.txt文件里,这里有一个问题就是strlen(message)需要+1吗?strlen求字符串长度,求到'\0'就结束了,也就是说如果+1就是把'\0'也写入到文件里,这里需要吗?答案是不需要,因为'\0'是C语言的要求,C语言不知道字符串从哪里结束才要'\0',但是和我文件有啥关系?
运行一下,在查看log.txt里的内容,发现果然hello world被写入到文件中了。
下面我们给log.txt里面多加几个2字符,然后在运行一下。
我们发现原来的内容全部没有了,这说明"w"方式,在写入之前,都会对文件进行清空处理!然后再从头开始写。
这个>重定向,是不是就是把log.txt打开,然后以w的方式把"hello world" 写进去呀?因此,我们>前面不加任何东西就是以w方式打开log.txt文件但是不写任何内容,此时就把log.txt清空了。
那如果我们就想要追加写呢?可以以"a"的方式打开,a在文件结尾,追加写。
3.fclose
如果我们把一个文件使用完毕了,就需要使用fclose关闭一下这个文件。它的使用非常简单,把打开的文件指针传进去即可。
下面就有一个问题了,文件是在磁盘上的,磁盘是外部设备,我们上述的fwrite,fopen,包括fclose,其实实在访问硬件,那我们用户能直接访问硬件吗?不能,操作系统不相信任何人,我们要访问硬件,必须通过操作系统提供的系统调用,因此,我们上述写的库函数,一定要封装系统调用!什么printf/fscanf/fwrite/fread......这些库函数,都是封装了系统调用的。下面我们就学习一下这些文件相关的系统调用。
三、文件系统调用
1.open
给我们提供了两个打开文件的系统调用,我们只要学会下面那个参数多的即可,参数少的是参数多的一子集。
第一个参数是要打开的文件路径,如果没有带路径,默认就是进程的当前路径。第二个参数是以什么方式打开,第三个参数是文件的权限,可以设置创建文件的权限。
返回值如果失败返回<0的数,成功,返回>0的数。
我们先来以只读方式打开,只读方式打开传递O_WRONLY这个宏即可。
我们发现我们直接打开文件失败了,这是为啥呢?这是因为如果打开的文件不存在,并不会给新建,因此此时要在传递一个宏O_CREAT, 表示如果文件不存在就创建。此时我们可以看到就创建了log.txt文件。
但是这里细心的同学会发现有问题,就是,我明明文件权限设置的是666呀,文件权限应该是rw-rw-rw,但这里却是rw-rw-r--,不是666而是664,这是因为权限掩码。如果你说我就要创建权限是666的文件呢?可以,有设置掩码的函数umask,直接把掩码设成0即可。
题外话:open的第二给参数是一个整数呀,可是我们给他传递了O_WRONLY和O_CREAT两个选项,是咋做到的呢? 其实就是简单的位运算。
#include "stdio.h"
#include "string.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>#define ONE (1 << 0) //1
#define TWO (1 << 1) //2
#define THREE (1 << 2)//4
#define FOUR (1 << 3) // 8void show(int flags)
{if(flags & ONE) printf("hello funcion1\n");if(flags & TWO) printf("hello funcion2\n");if(flags & THREE) printf("hello funcion3\n");if(flags & FOUR) printf("hello funcion4\n");
}int main()
{show(ONE);printf("----------------------------\n");show(TWO);printf("----------------------------\n");show(ONE | TWO);printf("----------------------------\n");show(TWO | THREE);printf("----------------------------\n");show(ONE | THREE | FOUR);printf("----------------------------\n");return 0;
}
通过位运算,我们就通过给1给标记位传递不同的值,让它表示多种信息。
2.write
第一个参数,就是对应文件的id,就是open的返回值,第二个参数是要写入的起始位置,第三个参数是写入的长度。
下面运行一下,看下结果。我们运行了两次,打印出来的都是一样的,之后我手动往log.txt里面加了一串b,在运行,发现,那一串b并没有被清空,因此,我们可以发现写入的时候是从头覆盖写的,但是并不会对文件做清空处理。
那如果我也想做到清空呢? 我们需要在打开文件的时候在加一个宏,O_TRUNC,截断的意思,就是每次打开文件都做清空。
如果我想做到如同C语言中的a一样,追加写呢?还有一个宏,O_APPEND。如果带了O_APPEND就要把O_TRUNC去掉,追加和清空是冲突的。
我们现在用的都是系统调用,fopen,就是用open封装的,"w"方式就会被转化成O_WRONLY | O_CAEAT | O_TRUNC.
这都没问题,但是有一个东西我们一直没谈,就是open的返回值可是一个int啊,但是fopen的返回值是一个FILE类型的指针,这两个玩意八竿子都打不着,有啥关系呢?下面我们就要谈谈文件的管理了。
3.访问文件的本质
操作系统里会有很多个进程,每个进程可能要打开很多个文件,这些被打开的文件要不要被被管理起来呢?要,先描述在组织。操作系统用struct file描述一个被打开的文件信息,struct file里应该包含什么呢?1.文件在磁盘的什么位置 2.文件的基本属性(权限,大小,读写位置,谁打开的...)3.文件的内核缓冲区,总之,这个结构体里包含了文件的大部分信息,类似的,struct file里还有一个strcut* next指针,每打开一个文件,内核创建一个struct file,然后用strcut* next指针链接到一起,此时操作系统要对文件进行增删查改就是对文件链表的增删查改,如果要添加一个文件,就在文件链表里插入,如果要关闭文件,就是把文件的所有属性释放掉,从链表删除,再把数据刷新到磁盘上。
一个进程可能打开多个文件,那些文件是被那个进程打开的呢?我怎么知道,所以,必然要建立进程PCB和打开文件struct file的对应关系。
那怎么建立的呢?在进程PCB里会存在一个指针,struct file_struct *f;这个指针指向struct file_struct结构体,这个结构体里面会包含一个数组,数组的名字叫做 struct file* fd_arrdy[],这个数组显然是个指针数组,这个数组的下标从0开始,数组每个元素的类型是 struct file*,所以,当我们打开一个文件的时候,操作系统会创建好struct file,然后在这个数组里分配一个下标,把创建好的struct file的地址,填到这个下标上,以后,每个进程就可以根据这个文件描述符表,就能把打开的文件找到。
所以,为啥open的返回值是个整数呢?open会创建一个struct file,然后在当前进程的文件描述符表里找一个没有用过的下标,把创建的struct file的地址填进去,然后把这个数组下标返回给用户,因此,这个int本质就是一个数组的下标。
所以,在我们写的时候,必须得把这个数组的下标传进去,进程通过指针找到文件描述符表,然后在通过这个数组下标,索引到文件的地址,从而往该文件写入。
文件和进程产生关联是通过数组下标关联的,这样就可以做到文件和进程的解耦。
这个文件描述符可还没见过呢,下面我们看看文件描述符是几呢?
我们可以看到是3, 下面我们多打开几个文件看看。
可以看到,是连续的整数。但是问题来了,0、1、2哪里去了呢?
4.stdin&&stdout&&stderror
C程序在默认启动的时候,会打开三个标准输入输出流(文件):stdin(键盘文件),stdout(显示器文件),stderr(显示器文件)。所以我们在打印的时候为啥要包含stdio.h呢?std就是标准的意思,io就是输入输出,是C语言会打开吗?任何语言都会打开这三个文件,这不是C语言的特性,是操作系统的特性,电脑在打开的时候,键盘和显示器文件默认就会打开,进程只需要把打开键盘,显示器文件的地址填入即可。因此0、1、2是被这3个家伙占着呢?怎么验证呢?
我们直接用write往1和2里面写入。1和2是显示器文件哦,直接打印出来了。
下面用read接口验证一下0号,键盘文件。
为啥卡住了呢?因为0是键盘文件,在等待键盘就绪!
现在问题又来了哦,可C语言的返回值是FILE指针啊,这和int有啥关系呢?FILE是C语言的内置类型吗?不是,FILE是C库里封装的一个结构体,这个结构体里面一定包含了该文件的数组下标,下面验证一下。
5.文件的引用计数
关闭文件的系统调用是close,现在我们把下标为1的文件stdout关闭。然后打印了stdout和stderr的fileno,fprintf的用法和printf基本一致,只不过前面加了一个文件描述符而已。我们可以看到,printf没有打印在显示器上打印出来,这肯定和我们关闭close有关,因此,printf底层肯定访问了stdout显示器文件,然后我们把stdout关闭,因此在屏幕上就打印不出来了。但是为啥stderr文件能打印出来呢?stdout和stderr都指向显示器文件,因此显示器文件的引用计数就是2,如果再来一个指向显示器,引用计数就会继续增加。当把stdout关闭,引用计数--变成了1,因此stderr还是能打印出来,关闭文件是把该下标的地址填成NULL。
printf也是有返回值的,其实stdout已经关闭了,但printf以为自己打印成功了,因此就把打印的字符个数13返回了过来。
四、重定向
1.文件描述符的分配规则
我们把2号文件描述符关闭之后,新创建的文件描述符就是2,因此我们可以得知,文件描述符的分配规则就是从0下标开始,寻找最小的没有被使用的数组位置,它的下标就是新的文件描述符。
2. 输出重定向
下面我们把2号文件描述符关闭,然后创建一个文件fd,之后调用write往1号文件里写入5次。
1号文件描述符对应的显示器文件,因此我们把内容写入到了显示器上。
下面我们把1号文件描述符关闭,然后创建一个文件fd,之后调用write往1号文件里写入5次。
我们发现,本来应该向1号文件描述符也就是显示器写入的信息,居然写到了 log.txt里,这是因为我们把1号文件描述符关闭了,然后又创建了一个文件,这个文件根据分配规则,就分配到了1号描述符,然后我们往1号描述符里面写,就写到了文件里。本来应该往显示器写却写入到了文件里,这就叫输出重定向。这里我们可以画张图理解一下。
这样写不是不可以,但是要先关一次,然后在打开一个文件,当别人问你为啥这么做的时候,你就要和别人解释半天,有没有一写系统调用能帮我们做这件事呢?打开文件就行了,然后重定向调用函数就行,有这样的接口吗?是有的。
3.重定向系统调用
是有dup,dup2,dup3系统调用的,常用的就dup2,因此我们详细谈谈dup2,dup就是duplicate,复制的意思,参数是2个文件描述符,一个旧的文件描述符,一个新的文件描述符。
那么问题来了,是把旧的文件描述符内容拷贝给新的文件描述符内容,还是新的文件描述符内容拷贝给旧的文件描述符内容呢?这样说吧,dup2之后,2个文件描述符内容全都变成newfd的还是oldfd的?常理来看应该是全都变成newfd吧,但实际结果是全都变成oldfd,这里挺奇怪的是吧,也不懂老外为啥这样起名字。因此如果我们要让1号文件描述符内容是新建的文件描述符fd的内容,要怎么传参呢?就要dup2(fd, 1)这样传参。下面我们来使用一下。
我们用dup2就实现了同样的效果。 上面的代码忘记close了,要记得close文件。
4.追加重定向
上面的代码中,文件是O_APPEND方式打开,我们多运行几次,这个log.txt就会越来越大,这就叫追加重定向。
5
5.输入重定向
read的第一个参数是文件描述符,要读哪个文件,第二个参数是读到哪,第三个是读多少个字节,返回值是实际读了多少个字节。
下面我们读取文件方式改为只读方式,然后读取0号文件,也就是键盘文件,阻塞住了,我们往键盘输入内容,然后回显出来了。
下面我们把0号重定向一下。
我们可以看到本来应该从键盘文件标准输入变读取,变为了从指定的文件读取,这就叫输入重定向。
重定向的本质,就是在内核里对文件的地址做拷贝。
6.1号VS2号
我们直接往1号和2号文件描述符里打印,运行,可以看到没问题,都打印出来了。但是当 ./myfile > normal.txt,也就是把1、2号文件的打印输出重定向到normal.txt文件的时候,为啥2号文件的内容没有重定向到nomral.txt里呢?为啥cat只能看到1号文件描述符重定向的内容呢?这是因为>是把1号显示器的内容重定向到了文件里,和我2号文件描述符有啥关系?
如果我想把正常消息打印到一个文件,错误消息打印到一个文件,该咋办呢?可以进行下图中的操作,这里其实非常直观,就是把1号文件的内容重定向到normal.log,2号文件的内容重定向到err.log里。默认不写的话是把1号重定向到文件。下面就多出来了err.log文件。
那如果我要把1、2的内容重定向到一个文件里咋办呢?
默认不写就是1号文件重定向到all.log文件,指令是从左往右执行的,&1(取地址1)的意思就是把1号文件的内容写入到2号文件里,因为左边的指令已经执行完了,1号文件的地址已经是all.log的地址了,然后把1号文件内容拷贝给2,此时1和2都指向了all.log文件。最后就能都写入到all.log里了。
相关文章:

linux文件与重定向
目录 一、共识原理 二、回顾C语言文件函数 1.fopen 2.fwrite 3.fclose 三、文件系统调用 1.open 2.write 3.访问文件的本质 4.stdin&&stdout&&stderror 5.文件的引用计数 四、重定向 1.文件描述符的分配规则 2. 输出重定向 3.重定向系统调用 4.…...

基于Python的仓库管理系统设计与实现
背景: 基于Python的仓库管理系统功能介绍 本仓库管理系统采用Python语言开发,利用Django框架和MySQL数据库,实现了高效、便捷的仓库管理功能。 用户管理: 支持员工和管理员角色的管理。 用户注册、登录和权限分配功能&#x…...

【Pikachu】URL重定向实战
人生在世只有一次,不必勉强选择自己不喜欢的路,随性而生或随性而死都没关系,不过无论选择哪条路,都不要忘记自己的初心。 1.不安全的url跳转实战 首先点击页面上的链接,观察url 直接修改url为https://www.baidu.com进…...

C语言实现3D动态爱心图形的绘制与动画效果
**标题:C语言实现3D动态爱心图形的绘制与动画效果** --- ### 一、引言 在计算机图形学中,三维图形的绘制和动画处理是一个重要且有趣的研究方向。通过数学公式描述的几何体可以在计算机屏幕上展示出丰富多彩的动态效果,其中“爱心”图形作…...

深入理解Nginx:从基础配置到高级优化
什么是Nginx? Nginx(发音为“Engine-X”)是一个高性能的HTTP和反向代理服务器,同时也可以作为邮件代理服务器和通用的TCP/UDP代理服务器。Nginx以其高并发处理能力、稳定性和灵活的配置闻名,是现代Web开发和部署的核心…...

ONLYOFFICE8.2版本测评,团队协作的办公软件
文章目录 引言ONLYOFFICE产品简介功能与特点1. 实时协作2. 兼容性3. 模板库4. 评论和修订5. 安全性 体验与测评功能测试 邀请用户使用项目介绍结尾了解更多 引言 在数字化办公的浪潮中,效率和协作成为了工作的核心。ONLYOFFICE作为一个强大的办公套件,正…...

spring 和 grpc 的整合
spring 和 grpc 的整合 首先我们要知道 grpc 中我们在使用的时候用到了 grpc 的那些东西 dil 的编写serverimplserverbuilder addService 客户端的 stub 编写 这里面我们看一下我们那些地方可能需要 spring 帮我们管理,那些地方我们需要自己来管理呢?…...

企业项目级IDEA设置类注释、方法注释模板(仅增加@author和@date)
文章目录 前言一 设置类注释1.1 添加模板1.2 复制配置 二 设置方法注释2.1 添加模版2.2 设置模版2.3 设置参数变量2.4 配置对应快捷键2.5 配置对应作用域2.6 使用方式 说明 前言 公司代码规范中,需要在标准JavaDoc注释的基础上加上作者和日期。网上虽然有很多现成的…...

1 设计模式原则之开闭原则
一、开闭原则 1.定义 开闭原则:对扩展开放,对修改关闭。 2.具体用法 在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。 想要达到这…...

前端大环境
需求增长: 数字化转型推动:企业和组织的数字化转型进程不断加快,对前端开发的需求持续增加。无论是企业官网、电子商务平台、在线办公系统还是各种移动端应用,都需要专业的前端开发来打造良好的用户界面和交互体验。新兴技术和平台…...

Electron: 主进程和渲染进程之间通信
// 渲染进程 向 主进程 异步通信// preload.js 预加载 const {ipcRenderer} require(electron) ipcRenderer.send(on-send-event, 这里是需要传递的参数) // 第一步ipcRenderer.on(on-resend-event, (e, data) > {console.log(data) // 打印的是ipcMain.on传递过来的参数&a…...

社交电商的优势及其与 AI 智能名片小程序、S2B2C 商城系统的融合发展
摘要:本文深入分析了社交电商相较于传统电商的优势,包括门槛低、易操作、更生活化和可团队化运作等特点。同时,探讨了 AI 智能名片小程序和 S2B2C 商城系统在社交电商发展中的作用,以及它们与社交电商融合所带来的新机遇和发展前景…...

蓝桥杯c++算法学习【4】之简单数论(阶乘约数、求值、循环小数、等差数列、最大比例:::非常典型的必刷例题!!!)
别忘了请点个赞收藏关注支持一下博主喵!!!! 关注博主,更多蓝桥杯nice题目静待更新:) 简单数论 一、阶乘约数 【问题描述】 定义阶乘n!123...n。 请问100! (100 的阶乘)有多少个正约数。 【答案提交】 这…...

重构代码之删除对参数的赋值
删除对参数的赋值 是一种重构技术,旨在消除对方法参数的重新赋值。这种实践可以增强代码的可读性和维护性,避免潜在的副作用。以下是详细讲解: 一、动机 保护参数的意图:方法参数通常表示传入数据或状态。如果重新赋值ÿ…...

Docker的基本概念、安装步骤以及一些简单的用法
Docker 是一种开源的容器化平台,允许开发者打包应用及其依赖项到一个可移植的容器中。容器可以在任何支持Docker的环境中运行,这使得应用的部署和管理变得更加简单和高效。 1. Docker的基本概念 在深入学习Docker之前,了解一些基本概念是很…...

VuePress v2 快速搭建属于自己的个人博客网站
目录 为什么用VuePress? 一、前期准备 Node.js 使用主题快速开发 二、VuePress安装 三、个性化定制 修改配置信息 删除不需要的信息 博客上传 四、部署 使用github快速部署 初始化仓库 本地配置 配置github的ssh密钥 部署 为什么用VuePressÿ…...

shell编程--永久环境变量和字符串显位
环境变量 echo $HOME 在终端输出后会显示家目录有个root变量 我们会提出个疑问为什么平时我们在终端输入sl 或者which等等命令会输出一些内容呢,这是因为这些命令都有对应的环境变量。 我们查看一下环境变量 在终端输入: echo $PATH 我们看一下输出…...

【优选算法篇】算法江湖中的碎玉拾光——C++模拟题全解,踏步逐章细细品味
文章目录 C 模拟题详解:基础题解与细致分析前言第一章:基础练习1.1 替换所有的问号(easy)解法(模拟)C 代码实现易错点提示时间复杂度和空间复杂度 1.2 提莫攻击(easy)解法࿰…...

【MySQL 保姆级教学】事务的隔离级别(详细)--下(14)
事务的隔离级别 1. 如何理解事务的隔离性2. 事务隔离级别的分类3. 查看和设置事务隔离级别3.1 全局和会话隔离级别3.2 查看和设置隔离级别 4. 事务隔离级别的演示4.1 读未提交(Read Uncommitted)4.2 读已提交(Read Committed)4.3 …...

部分利用oracle数据字典查询对应信息的语句。
查看当前用户的缺省表空间 SQL>select username,default_tablespace from user_users; 查看当前用户的角色 SQL>select * from user_role_privs; 查看当前用户的系统权限和表级权限 SQL>select * from user_sys_privs; SQL>select * from user_tab_privs; …...

实例教程:BBDB为AHRS算法开发提供完善的支撑环境(上)
1. 概述 本教程将结合程序代码及CSS控制站工程,讲述如何基于PH47代码框架的BBDB固件版本,为开发自己的AHRS姿态解算算法提供完善支撑环境,以及数据分析手段。 BBDB固件已内置了一套姿态解算算法。对于需要进行AHRS算法开发研究的开发者&…...

k8s搭建1.23版本
文章目录 1、前期准备1、关闭防火墙和selinux2、关闭交换分区3、修改主机名和免密登录4、内核参数5、安装docker6、安装k8s源 2、安装1、安装k8s软件包2、初始化k8s3、安装calico网络插件4、检查 1、前期准备 以下操作所有主机都要运行的 1、关闭防火墙和selinux systemctl …...

【MYSQL】分库分表
一、什么是分库分表 分库分表就是指在一个数据库在存储数据过大,或者一个表存储数据过多的情况下,为了提高数据存储的可持续性,查询数据的性能而进行的将单一库或者表分成多个库,表使用。 二、为什么要分库分表 分库分表其实是两…...

CSS基础知识05(弹性盒子、布局详解,动画,3D转换,calc)
目录 0、弹性盒子、布局 0.1.弹性盒子的基本概念 0.2.弹性盒子的主轴和交叉轴 0.3.弹性盒子的属性 flex-direction row row-reverse column column-reverse flex-wrap nowrap wrap wrap-reverse flex-dirction和flex-wrap的组合简写模式 justify-content flex-s…...

常见error集合
Cannot use import statement outside a module 原因:在commonJS中用了es6的语法,import。分析: 一般我们的运行环境按照模块化标准来分,可以分为es6和commonJS两种,在es6中引入模块用import,在commonJS中…...

建筑施工特种作业人员安全生产知识试题
1.因生产安全事故受损害的从业人员,除依法享有工伤社会保验外。依照有关民事法律尚有获得赔偿的权利,有权向本单位提出(D)。 A.任何要求 B.保护要求 C.辞职要求 D.赔偿要求 2.为了加强建设工程安全监督管理&…...

2024140读书笔记|《作家榜名著:生如夏花·泰戈尔经典诗选》——你从世界的生命的溪流浮泛而下,终于停泊在我的心头
2024140读书笔记|《作家榜名著:生如夏花泰戈尔经典诗选》——你从世界的生命的溪流浮泛而下,终于停泊在我的心头 《作家榜名著:生如夏花泰戈尔经典诗选》[印]泰戈尔,郑振铎译,泰戈尔的诗有的清丽,有的童真&…...

JSP是如何被执行的?
JSP(JavaServer Pages)是一种用于构建动态Web页面的技术,它允许开发者在HTML、XML或其他文本格式的文档中嵌入Java代码。JSP页面在服务器端被编译成Servlet,然后由Servlet容器(如Tomcat)执行。以下是JSP页面…...

用python中的tkinter包实现进度条
python中的tkinter包是一种常见的设计程序的GUI界面用的包。本文主要介绍这里面的一个组件:进度条(Progressbar)。Tkinter Progressbar里面对进度条组件已经做了一定的介绍,但比较抽象。本文以另一种方式介绍这个组件及其常用用法…...

oneplus3t-lineageos-16.1编译-android9
本仓库开发已经完毕,使用请直接从4.2开始 ** LineageOS16_oneplus3t仓库群克隆 、 编译 、 刷机** 编译过程若ctrlc强制终止,请重新从头编译 LineageOS16_oneplus3t仓库群克隆过程 LineageOS16_oneplus3t仓库群克隆过程描述: LineageOS16_oneplus3t_gitRepoLs_c…...