Hi 你好,下面我们一起来学习呢文件内容的读写
文件内容的读写呢它实际上是靠这个流
那么这个流呢,我们前面提到了又分成 文本流和二进制流。
那我们先看文本流 那文本流呢也就是文本文件的操作呢,它是靠 SteamReader
和 StreamWriter 来实现的 那一般呢我们 new 一个
StreamReader 当然包括文件路径和这个文件的编码
因为我们知道如果是文本的话,它一定有编码问题,它是国标编码 还是
Unicode 编码,还是 UTF8 编码。
所以这是一个 StreamReader 的建立一定要指明它的这个编码方式
然后 StreamReader 的读写,它的读的方法 包括
ReadLine 读一行,还有 ReadToEnd
直接 读取所有的,所有的内容,当然也包括
Read 读取一个字符,等等
StreamWriter 呢类似,它有 WriteLine Write
和 Flush、 Close 那么 WriteLine 是写一行,也就是写的时候呢
带一个换行符,普通的 Write 呢就写普通的字符串 Flush
呢是让它实际写到文件里面去 这个文本文件的操作呢
这两个类呢它是这样使用的,主要是用这两个对象以及它的方法 下面我们看几个例子。
第一个呢我们看 LogToFile 第二个例子呢我们看一个
CopyFile AddLineNumber。
就是第一个呢是 表明了它是怎么写日志,第二个呢我们看怎么样读取文件
并拷贝到一个新的文件。
好,请看第一个 例子,就是 LogToFile 这个函数。
我们有一个文件名 有一个文件名,有这个文件名,然后它要用的方法呢比较简单
就是 StreamWriter,new 了一个 StreamWriter
文件名 然后呢它给的是一个是否 是否,就是是否创建。
然后后面呢有一个叫 System.Text.Encoding.Default,这样
这样一个编码方式呢就是系统默认编码
系统默认编码呢,当然我们的中文的 Windows 系统呢它就是
就是这个中文的国标,或者叫 GBK
的编码 然后它用的方法就是 Writer.Write WriteLine,
WriteLine,另外呢我们写完以后呢要 Write.Close。
所以这个方法呢 它我们反复地调用,如果文件已经存在的话它就是
Append 就是追加 所以这样就可以写,写日志。
当然我们 在这里呢加了一些其他的写上时间啊等等。
所以总的说来 它是用一个 Writer 就可以把这个相关的事情做了
这一段代码呢也是我们在日常工作当中呢经常用的 有了这个函数我们就可以向日志里面写点儿东西。
下面我们看第二个例子 叫复制文件并且加上行号,那
这里呢从一个文件里读然后写到第二个文件,从第一个比如说 cs
文件里面读 然后呢写到一个新的文本文件里去,那在这里面
我们就创建了一个 FileStream 然后呢这个
FileStream 再包装成一个 Reader 和一个
Writer 就是由文件流然后包装成一个 Reader 或者 Writer。
然后 Reader 和 Writer 呢我们就可以用它呢 每读取一行,从那个文件里面每读取一行
只要这个读的行不是 null 就说明读到内容了,然后我们要做的事情呢
就是去掉它的,做一些处理。
比如说这里是去掉 这个源程序里面的注释,然后再往新的文件里面
写一行,同时呢加上一个行号和一个冒号
然后呢再加一个 \t,也就是说加一个
字表对齐位置,然后我们也同时把它写到控制台上为了看着方便
最后呢把两个对象关闭 所以它的一个基本的过程就是一个循环的读取
然后呢再向新文件里面写入的一个过程。
就是在拷贝的同时 也做了一个,一些处理。
当然这个处理呢包括加行号,包括去注释 好我们看一下去注释,去注释呢
它实际上就是找到这个双引号,双斜杠之后的 那个位置
IndexOf,找到这个位置 然后呢 Substring
明到这个位置,也就是说 这样的话我们得到的呢就是去掉行号的这个类
总的说来,文本文件的操作呢它就是用这个 StreamReader
和 StreamWriter 来处理的。
再看看二进制文件 二进制文件呢我们可以用 FileStream 直接操作。
那么这个 FileStream 呢就有 Seek 和
Read 等等方法 所以也就是,Seek
呢就是读写指针,走到那儿 有点像我们 C
语言里面的,C 语言 文件的存取,所以这个就是
FileStream 下面我们看一个例子,它是
从 Bmp,就是我们平时的位图文件,就是 Windows 画笔啊
画出来的那个保存的文件 bmp 文件 读取每一个信息,然后呢把它显示出来
大家知道呢平时的这个文件啊 它都是有很多的字节
但每一个字节呢它都规定了它的含义,所以实际上我们这个 bmp
文件呢它是 它的内容呢,格式是公开的,所以我们只要按照它这里面方式去读取呢
就可能读取到它里面的内容。
我们下面看一下。
好 下面我们看这个读取 bmp 文件的那个例子
在这个例子里头呢,bmp 文件它前面呢实际上是一个 FILEHEADER,
BITMAPFILEHEADER 这个FileHeader 我们用一个 Struct 来表示。
注意这个 Struct 呢我们前面 加了 attribute,就是 StructLayout
它表示呢 这里面这些字段的布局,也就是说,现在呢是用一个什么方式呢 Sequence
就是顺序的,也就是说 它表明了我们这里面的这几个字段呢是顺序存放,不能乱存放
另外一个呢,它加了一个,一个属性呢叫 Pack
= 1 也就是说它是相邻地存放,一个字节挨一个字节
对齐到每一个字节,也就是相邻地存放。
那这里面实际上前面两个字节啊 是一个
short,是 bm,那就是 bitmap 那两个字母
然后呢有文件呢大小,还有保留字,然后还有一个比较关键的 是它的对齐位置。
然后呢在 后面,就是文件头后面呢又有一个结构 就叫信息头,INFOHEADER。
这个信息头呢里面包括 宽度、
高度,然后呢一共 有多少位,每一个点用多少位来表示
等等等等,所以这个呢是信息头 再后面呢才是真正的那个每一个点的信息
我们这里呢是一个三元组 Triple,一个像素点用三个字节
就是红、 绿、 蓝,红绿蓝由于呢
在计算机里面它这个顺序呢 是红排到后头的,也就是相当于
高字节,就红绿蓝 这个红呢高字节排到后头,三个字节。
这就是它里面的几个结构 那我们下面呢看看这个读取,这个读取呢它的基本的方法呢就是
有个 FileStream,然后呢读取这个头。
读取这个头呢就 然后呢再读取信息,等等。
那这两个读取呢都是用的 用 Seek,然后呢直接 Reader
一个 buffer,Read 读取好多个字节,读取一个字节,读取完了以后呢,这里
我们为了方便呢用了一下指针,所以在这个指针呢是 unsafe
用了指针,这个指针呢实际上就是我们的,这个指针实际上就是 数组。
所以我们把它呢用指针呢直接放到这里头,更方便一点
读取了以后呢,下面我们就可以呢一个字节一个字节地 读取了。
当然现在读取呢是读取一个三元组,顺序的有多行、
多列 读取了以后呢就得到一个三元组,这个三元组呢我们把它
红绿蓝呢组成一个颜色,最后呢我们再画到屏幕上 要注意的是呢,这个
bmp 呢是从下向上存的 也就是说它是最底下那一行先存,这是第一
第二个要注意的呢就是说如果每一行占的那个字节数不是 4
的倍数的话 它是有个零头,空了几个字节,所以我们要把它 Seek,要给它忽略过去
这段代码呢有点点啰嗦,请大家呢对照这个源程序 再仔细地去看一下。
那另外我们顺便说一下有个序列化 这个序列化呢也是比较重要的一个概念
它实际上就是帮我们的信息啊,特别是对象 把它呢序列化成某种格式。
那一般的呢就是能够 表示成一串字节,相当于这样的
当然我们也可以把它用二进制的这个格式进行序列化,我们也可以把它 格式化成 Xml 这个格式。
那么要格式 要能够序列化,要求在对象呢标注一个
Serializable 就是可序列化的,那么它才会用这两种格式呢进行处理
现在呢这个例子比如说有个书目的信息 book,我们标注一个可序列化
标注可序列化以后呢,在这里面我们 对于这样一个
book 对象,一个 BinaryFormatter 这样一个
格式化对象,有了这个对象以后呢,我们就可以 用
Serialize 这个方法把它序列化到一个 Stream 流里面去。
所以这样一个序列化过程。
同样的我们也可以 Deserialize
就是反序列化,也就是从这个流里面呢得到这个对象,然后强制类型转换
所以这个序列化呢就是这样一个概念,就是把它可以
序列化到一个文件流里面,当然也可以序列化到网络里面