20191205张潇——学习笔记2
一、知识点总结
一、文件操作都有什么?
- 什么是文件?
文件是存储在外部介质上的以文件名标识的数据的集合。存储在磁盘上的文件称为磁盘文件,输出到打印机上就是一个打印机文件。与计算机相连的设备称为设备文件,因此广义地说,任何输入输出设备都是文件。
- 文件的分类:
根据数据性质,文件可分为:程序文件(可由计算机直接执行的程序)和数据文件(用来存放普通的数据,必须由程序来存取和管理)。
根据数据的编码方式,文件可分为:ASCLL文件(可用字处理软件建立和修改)和二进制文件(以二进制方式保存的文件,它不能用字处理软件编辑,占空间较小)。
根据数据的存取方式和结构,文件可分为:顺序访问文件、随机访问文件和二进制文件。
- 文件的打开、关闭与读写
为访问存放在外部介质上的数据,应先按文件名找到所指定的文件,然后再从该文件中读取数据。文件名指的是:设备名:\文件所在的路径名\主文件名.扩展名;在VB中,文件说明没有大小写之分。
文件结构:为了有效地存取数据,数据必须以某种特殊的方式存放,这种特定的方式称为文件结构
- 文件的组成
文件由记录组成,记录由字段组成,字段由字符组成
字符:构成文件的最基本的单位;字段或域:由若干个字符组成,用来表示一项数据;记录:就是一组有相互关系的字段;文件:是记录的集合。
- 文件的读写
(1)打开(建立)文件:一个文件必须先打开或建立后才能使用;
(2)进行读、写操作:把内存中的数据传输到相关联的外部设备并作为文件存放的操作叫做写数据;把数据文件中的数据传输到内存中的操作叫做读数据。
(3)关闭文件
- 二进制文件
概念:以二进制方式保存文件,以字节数来定位数据,没有固定的格式,允许程序按所需的任何方式组织和访问数据,对文件中的各个字节数据进行存取访问和改变。二进制文件不能用普通的字处理软件进行编辑,但占用的空间较小。
二进制文件的操作与随机文件类似,区别在于二进制文件的访问单位是字节,而随机文件的访问单位是记录。
任何类型的文件(顺序文件或随机文件)都可以使用二进制访问模式打开。二进制存取可以获取任何一个文件的原始字节。
二进制使用GET#语句获取数据;用PUT#语句写入数据
- 打开二进制文件
格式:open文件名 For Binary As[#]文件号
说明:文件名:字符串类型,指定文件的路径与文件名;For Binary:以二进制方式打开的文件既可以读也可以写,如果文件不存在,则新建文件。
- 写二进制文件
二进制文件的写操作使用PUT语句。
格式:PUT[#]文件号,[写位置],表达式。
功能:将表达式的内容写入文件中,一次写入的长度等于表达式的长度。
说明:文件号——已打开的二进制文件的文件号;写位置——指定数据要写入文件中的位置(从开头以字节为单位计算),若省略,则紧接上一次写作的位置写入。若尚未读写,则为文件头;表达式——要写入文件中数据。
- 读二进制文件
二进制文件的读操作使用Get语句
格式:Get[#]文件号,【读位置】,变量名
功能:是将一个已打开的二进制文件的指定位置读取长度等于变量长度的内容到变量中。读出数据后,指针移动变量长度的位置。
说明:文件号——指定要读取的随机文件的文件号;读位置——指定要读入的数据在文件
的位置(从文件开头以字节为单位)。若省略,则紧接上一次操作的位置开始读。若尚未读写,则从文件头开始读入;变量名——保存读入的数据。
- 文件操作的级别
(1)硬件级别、(2)操作系统内核中的文件系统函数、(3)系统调用、(4)I/O库函数、(5)用户命令、(6)sh脚本
二、文本文件和二进制文件如何转换?
首先从C语言的角度来看,所有的文件都可简单的分为两类:一类是文本文件,另外一类是二进制文件。
1、文本文件:
所谓的文本文件,就是按照字符的编码规则(比如ASCII),1:1的根据你敲的字符形成的机器码文件。后缀习惯是以.txt结尾。一个典型的文本编辑器就是大家熟悉的记事本程序(notepad.exe)。
一个标准的ASCII文本文件,就是按照ASCII表的编码规则来进行1:1转换的。当然如果你是按照unicode编码,所有的字符按照两个字节代表一个字符的方式进行编码。在解析Unicode编码的文本文件时,就要按照两个字节为一个字符的方式进行二进制到文本的转换,这样才能正确解析。
2、二进制文件
二进制文件是可以认为是所有非文本文件都称之为二进制文件。要打开二进制文件,需要有形成这类文件的程序的内置的解析器,才能解读。这也解释了为什么不同的文件比如pdf,docx等文件,在编程的时候,必须要有相应的文档解析类函数来完成的原因了。
当然你完全可以用二进制方式打开任何一个文本文件,因为底层上就是那些代码,你只需要读取每一个字节,查找转化成相应字符予以显示就可以了,因为是你知道ASCII表的规则。
- 二进制文件和文本文件的转换:
首先要修改二进制文件:使用vim修改:
vim -b 文件名、:%!xxd ——转化成16进制、然后进行修改二进制、:%!xxd -r——转回去、最后:wq
第二步把二进制文件转化成其他文本文件搜索ASCII字符:
1.先使用iconv命令:(IGNORE忽略那些翻译不了的)
iconv -f GB2312 -t UTF-8//IGNORE {} -o $filename.text
2.再使用grep 对 *.text 进行搜索想要查找的ASCII字符;
说明:
1.编译器是怎么回事?
所谓编译器,顾名思义就是将一种文本格式转换成另一种文本格式。比如将字符串 echo "hello"; 转换成 printf("hello"); 这其实是php语言转成c语言的一种表示。这只是一种简单的描述,其实很大一部分的编译器是将源语言转换成了汇编语言。(通过编译器后,编译器把这个翻译成了另一套字符串,其实就是汇编语言)
- 字符串是什么?
字符串其实也是二进制,只不过字符串它不能执行而已。当我们查看字符串的16进制的时候,其实和二进制的16进制一样,只是我们人为的给字符串赋予了一个abcde...这样的一层显示方式。汇编器其实和编译器做的动作是一样的,只是抽象的层次不同。当我们编译的时候,我们发现了文本文件要比可执行文件小很多,文本文件比汇编文件小6.5倍。而比二进制要小70倍左右,也就是说一个60字节的文本文件编译成汇编是400个字节左右,再生成二进制大概是4k左右了。
- 综上所述:
二进制其实和我们一般说的ASCLL中的FF,0F是一样的,只不过二进制符合的不是ASCLL的这套显示或者作用标准,它采用的是计算机CPU的处理标准。比如\x41在ASCLL中表示的是A,而到了计算机CPU那里他可能是另一个意思。
所以文本可以显示,而二进制却不能,是因为文本文件是通过文本文件查看器去重新给文本文件进行处理然后显示的,并不是我们想当然的“直接打开”就能看见,而二进制进行运行,则是不通过其他软件的,直接丢给CPU的。对于windows的二进制放到linux下能用吗?这一问题我查询了CSDN相关网站,发现其实这是不行的,windows的二进制放到linux下之所以不能运行,并不是二进制本身的问题,而是因为linux里没有windows的库,二进制文件运行的时候缺少必要的库才无法运行。所谓的库,其实就是调用系统资源或者本身就是系统资源的一种程序包(比如显示,接受键盘,窗口)。和二进制代码有关的唯一的其实就是CPU,因为不同的CPU处理的二进制的指令是有区别的。
三、数据结构如何读写?
1.读操作
#include<unistd.h>
int read(int fd,void *buf,int nbytes);
Read()将n个字节从打开的文件描述符读入用户空间中的buf[]。返回值是实际读取的字节数,如果read()失败,会返回-1,例如当fd无效时。注意,buf[]区必须有足够的空间来接收n个字节,并且返回值可能小于n个字节,例如文件小于n个字节,或者文件无更多需要读取的数据。还要注意,返回值是一个整数,而不是文件结束(EOF)符,因为文件中没有文件结束符。文件结束符是I/O库函数在文件流无更多数据时返回的一个特殊整数值(-1)。
2.写操作
#include<unistd.h>
Int write(int fd,void *buf,int nbytes);
write()将n个字节从用户空间中的buf[]写入文件描述符,必须打开该文件描述符进行 写、读写或追加。返回值是实际写入的字节数,通常等于n个字节,如果write()失败,则为-1,例如由于出现无效的fd或打开fd用于只读等。
以下代码段使用open()、read()、Iseek()、write()和close()系统调用。它将文件的第一个1KB字节复制到2048字节。
char buf[1024];
int fd=open("file",O_RDWR); // open file for READ-WRITE
read(fd, buf[ ],1024); // read first 1KB into buf[ ]
lseek(fd, 2048, SEEK_SET); // lseek to byte 2048
write(fd, buf,1024); // write 1024 bytes
close(fd); // close fd
另附课堂笔记:
GDB:
调试命令:gcc -g testgdb.c -o tg;debug:调试信息;release:没有调试信息
在Linux系统里可以用gdb(没有代码)、cgdb(有代码)、ddd来进行调试
错误类型分为两种:语法方面、逻辑方面;运行分为:单步运行(run、step、next、continue)、断电(函数:b main;行断电:b 数字;临时断点:tb或使用until跳过)
p i:打印变量的值;函数调用时优先使用next,单步执行时再使用step;同时有静态库、动态库时优先使用动态库;
(中间空格按TAB键即)
二、最有收获的内容
通过预习教材第九章,我收获最大、印象最深的是如何使用文件来编程和文件系统控件,我的总结如下:
首先在VB中,根据文件的读写模式,文件分为了三种:顺序文件(input、output、append);随机文件(random);二进制文件(binary)
其次文件系统控件也有三种:驱动器列表框、目录列表框、文件列表框
另外我总结了一些Linux下文件操作的命令:
一、文件目录操作
1、查看当前所在目录pwd
2、查看目录下文件ls -a
3、以列表形式显示目录下文件ll
4、打开目录cd(绝对路径和相对路径,如目前在根目录,有文件目录/usr/local,进入usr,执行cd usr和cd /usr都可以,在usr里面进入local,执行cd /usr/local和cd local都可以,如果要倒回上一级目录执行cd ..如果要倒回到根目录执行/)
5、创建文件目录mkdir(如mkdir test)
6、删除文件目录前询问用户rm -ri(如执行rm -ri test1后会出现rm:是否删除目录 "test1",输入y回车就删除了)
7、直接删除文件目录rm -rf(如执行rm -rf test2回车就删除test2了)
8、复制文件命令cp(如/usr/local/test里面有test1和test3,现在需要将test3复制到test1里面,执行cp -rf /usr/local/test/test3 /usr/local/test/test1)
9、修改文件名mv(如/usr/local/test里面有test1和test2和test3现需要将test1文件名修改为test4,执行mv /usr/local/test/test1 /usr/local/test/test4)
10、移动文件mv(如/usr/local/test里面有test2和test3和test4现需要将test4移动到test2里面,执行mv /usr/local/test/test4 /usr/local/test/test2)
二、文件查看
1、从文件开始显示文件的前n行内容head -n(如/etc里面有一个shadow文件用于存放用户信息的文件,我们要查看他的前三行文件执行head -3 shadow)
2、从文件开始显示文件全部内容cat(如cat shadow)
3、从文件结尾显示文件的后n行内容tail -n(如tail -3 shadow)
4、动态加载某个文件的内容tail -f(如/var/log里面有一个文件messages记录用户操作日志,tail -f messages)
三、文件编辑命令
1、打开文件vi(如/etc里面有一个文件hosts,要打开这个文件执行vi hosts)
2、进入编辑模式i,a(打开hosts后不能进行编辑,输入i之后出现---insert就进入编辑模式可以进行编辑了)
3、退出编辑模式,按下Esc
4、进入命令模式,按下:
5、退出但不保存q!
6、退出保存wq或x
7、保存w
三、问题与解决思路
问题1:linux下如何复制指定目录下的全部文件到另一个目录?
解决思路:linux下进行复制的命令为cp。假设复制源目录为dir1 ,目标目录为dir2。怎样才能将dir1下所有文件复制到dir2下?是我思考的问题。其解决办法如下:
(1)如果dir2目录不存在,则可以直接使用
cp -r dir1 dir2
即可。
(2)如果dir2目录已存在,则需要使用
cp -r dir1/. dir2
(3)如果这时使用cp -r dir1 dir2,则也会将dir1目录复制到dir2中,明显不符合要求。
(ps:dir1、dir2改成对应的目录路径即可。)
linux下复制整个文件夹的文件到另一个文件夹过程如下:
cp -ri A/B/* A1/B1/ 回车
若复制过程中询问是否覆盖,输入y按回车,若不想看到提示直接覆盖使用-rf
另外若A A1不在同一目录下,最好填绝对路径,就是/xxx/xxx/A/B/* /xxx/A1/B1/
比如:
cp -ri /home/server/tomcat/* /home/server/test/
cp: target `/home/server/test/' is not a directory
需要先创建目标文件夹
mkdir /home/server/test
cp命令的功能是将给出的文件或目录拷贝到另一文件或目录中,同MSDOS下的cp命令一样,功能十分强大。
语法:cp[选项] 源文件或目录、目标文件或目录
说明:该命令把指定的源文件复制到目标文件或把多个源文件复制到目标目录中。
该命令的各选项含义如下:
- a:该选项通常在拷贝目录时使用。它保留链接、文件属性,并递归地拷贝目录,其作用等于dpR选项的组合。
- d:拷贝时保留链接。
- f:删除已经存在的目标文件而不提示。
- i:和f选项相反,在覆盖目标文件之前将给出提示要求用户确认。回答y时目标文件将被覆盖,是交互式拷贝。
- p:此时cp除复制源文件的内容外,还将把其修改时间和访问权限也复制到新文件中。
- r:若给出的源文件是一目录文件,此时cp将递归复制该目录下所有的子目录和文件。此时目标文件必须为一个目录名。
- l:不作拷贝,只是链接文件。
需要说明的是,为防止用户在不经意的情况下用cp命令破坏另一个文件,如用户指定的目标文件名已存在,用cp命令拷贝文件后,这个文件就会被新源文件覆盖,因此,建议用户在使用cp命令拷贝文件时,最好使用i选项。
问题2:为什么不能把文件复制到文件本身或者不能将目录复制到目录本身中?
解决思路:我通过查阅百度百科发现一些回答:这种操作是不可以的,因为这是系统决定的。windows的文件系统规定是这样的,就是同一层次文件夹下不能出现相同的文件,不然就会给你加个复件的字样。不过可以给文件随便改下名,哪怕是大小写区分下也行,或者随便加个符号,就可以复制了。
基于此,我搜索了Windows的文件系统规定与这方面相关的知识:FAT文件系统是根据其组织形式(文件分配表)而命名的,文件分配表位于卷的开头。为了防止文件系统遭到破坏,FAT文件系统保存了两个文件分配表。文件分配表和根目录必须放在磁盘的一个固定位置,这样系统在启动时才可以找到需要的文件。NTFS具有许多优秀的性能,如文件和目录的安全机制,磁盘配额,文件压缩以及加密,而且当系统不正常中止后,文件系统可用自动恢复目录和文件的结构信息。
问题3:一个系统就一个分区好吗?
解决思路:如果是以前的话,我会说不好,我解释的原因也很简单就是因为不方便管理自己的系统,万一系统失灵了就十分的悲惨。
而现在了解到了一些知识,我认为不见得分区多了是好事情,因为我发现分区多了,对于系统查询东西会非常的慢,还有不利于存储,会在一定程度上降低读写的速率。对于系统故障问题,我相信这个不是什么问题,如果这个还算是问题的话,我想不出什么,也不知道说什么好,就只能说多装装系统,多上网查询如何解决系统故障的问题就可以了。
四、实践内容
虚拟机下Linux系统的基本操作vi编译器使用
一、实验目的:
1.理解vi的三种运行模式及其切换方法。
2.学会使用vi的各种操作命令进行文本文件的编辑。
3.用vi编写Linux下C程序,会用gcc编译。
二、实验环境:
一台装有Linux的机器,系统里边有gcc编译器。
三、实验内容:
- 基本实验
(1)不保存直接退出
1.在系统提示符下,输入vi,按回车键。
2.显示的vi界面。
3.输入 :q,不保存直接退出。
(2)新建文件hello.c并编译一段文字进行保存
1.在系统提示符下输入vi hello.c,按回车键。
2.显示vi界面,其编译界面左下角。
3.输入i,左下角会出现“插入”。
4.输入一段文字。
5.按Esc键,进入命令模式。这时“插入”不见了。
6.输入 :wq,按回车键,保存文件。
(3)对文件hello.c进行增、删、改操作
1.在系统提示符下输入vi hello.c,按回车键。
2.显示vi界面,其编译界面左下角。
3.输入i,进入插入模式。
4.输入增加的文字“vi is very easy to user~!”。
5.按Esc键,进入命令模式。
6.用“k”将光标移到“after use me,maybe you will love me~!”行任意处。
7.输入命令dd,删除光标所在一行(若连续输入d,d是将光标所在行及以下所有行删除)。
8.用方向键将光标移到anything的第一个“n”处。
9.按Esc键,进入命令模式。
10.输入命令2x。
(4)对文件hello.c进行复制、粘贴操作
1.接着步骤(18)继续做。
2.输入命令2yy,进行复制。
3.将光标移到“you can do athing you like~!”。
4.按Esc键,进入命令模式。
5.输入p,完成粘贴。
2.用vi编译器编写一个简单的程序(程序名为hello.c)
写入程序代码:(打印100~200之间的素数)
#include<stdio.h>
int main()
{
int i=0;
int count=0;
for(i=101;i<=200;i+=2)
{
//判断i是否为素数
int j=0;
for(j=2;j<i/2;j++)
{
if(i%j==0)
break;
}
if(j>=i/2)
{
count++;
printf("%d ",i);
}
}
printf("\ncount=%d\n",count);
return 0;
}
按Esc键,进入命令模式,输入:wq保存退出;在输入“gcc -o su hello.c”进行编译,若成功则不会有任何信息,反之,系统会报错;若成功,则输入“./hello”,就可以了。
报错现象如下:
编译成功现象如下: