C#基础知识复习3:装箱、拆箱-文件操作-对象序列化

来源:互联网 发布:java项目描述怎么写 编辑:程序博客网 时间:2024/06/03 19:18

1、补充(装箱、拆箱):box、unbox
(1)比较泛型集合List与ArrayList的性能。循环增加整数、引用类型比较性能。(装箱、拆箱 )见备注。
(2)装箱、拆箱必须是: 值类型→引用类型 或 引用类型→值类型。
object,接口。值类型是可以实现接口。
Person p=new Student();//这个叫隐式类型转换,不叫装箱。
Student stu=(Student)p;//这个叫显示类型转换,不叫拆箱。
int类型能装箱到object类型,因为object类型是int类型的父类。但不能装箱到string类型或Person类型,
拆箱时,必须用装箱时的类型来拆箱
装箱时如果是int,拆箱必须用int,不能用double
(3)方法重载时,如果具有该类型的重载,那么就不叫拆箱或装箱。int n=10; Console.WriteLine(n);//没有发生装箱,因为方法重载。
2、文件操作常用相关类
static File //操作文件,静态类,对文件整体操作。拷贝、删除、剪切等。
static Directory //操作目录(文件夹),静态类。
DirectoryInfo //文件夹的一个“类”,用来描述一个文件夹对象(获取指定目录下的所有目录时返回一个DirectoryInfo数组。)
FileInfo//文件类,用来描述一个文件对象。获取指定目录下的所有文件时,返回一个FileInfo数组。
Path//对文件或目录的路径进行操作(很方便)【字符串】
Stream//文件流,抽象类。
FileStream//文件流,MemoryStream(内存流),NetworkStream(网络流)
StreamReader //快速读取文本文件
StreamWriter//快速写入文本文件
GZipStream
3、Path类(对字符串操作),不用刻意记。
目录和文件操作的命名控件System.IO
string ChangeExtension(string path, string extension) (*)
修改文件的后缀,“修改”支持字符串层面的,没有真的给文件改名
string s = Path.ChangeExtension(@”C:\temp\F3.png”, “jpg”)
string Combine(string path1, string path2)
将两个路径合成一个路径,比用+好,可以方便解决不加斜线的问题,自动处理路径分隔符的问题
string s = Path.Combine(@”c:\temp”,”a.jpg”)
string GetDirectoryName(string path) (*)
得到文件的路径名。Path.GetDirectoryName(@”c:\temp\a.jpg”)
string GetExtension(string path) 得到文件的扩展名
string GetFileName(string path) 得到文件路径的文件名部分
string GetFileNameWithoutExtension(string path) 得到去除扩展名的文件名
string GetFullPath(string path) 得到文件的全路径。可以根据相对路径获得绝对路径。
string GetTempFileName() 得到一个唯一的临时文件名(*)
string GetTempPath() 得到临时文件夹的路径(*)
4、操作目录(Directory)
资料管理器
为了实现目录树,所以要掌握读取目录的类
Directory和DirectoryInfo
void Delete(string path, bool recursive) 删除目录, recursive表示是否递归删除,如果recursive为false则只能删除空目录
bool Exists(string path) 判断目录是否存在
string[] GetDirectories(string path) 得到一个目录下的子目录
string[] GetDirectories(string path, string searchPattern, SearchOption searchOption) 通配符查找目录下的子目录,可以搜索到隐藏文件。
static string[] GetFiles(string path) 得到一个目录下的文件
string[] GetFiles(string path, string searchPattern, SearchOption searchOption) 通配符查找目录下的文件
DirectoryInfo GetParent(string path) 得到目录的父目录
move() //移动、剪切。只能在同一个磁盘中。目录没有Copy方法。可以使用Move()方法实现重命名。
create()
资料管理器
通过treeview显示两级目录
动态添加treeview节点。di.GetDirectories()获取所有的根文件夹
TreeNode tn = new TreeNode();
tn.Text = d.Name;
tn.Tag = d.FullName;
treeView1.Nodes.Add(tn);
遍历根文件夹的同时添加二级节点,三级节点上添加文件的名儿
双击文本节点(怎么判断是否是文本节点?)在文本框中显示资料的内容
递归的方式 显示无限极节点
6、操作文件(File)
(1)文件编码
产生乱码的原因(只有文本文件才会乱码):文本文件存储时采用的编码,与读取时采用的编码不一致,就会造成乱码问题。解决:采用统一的编码就ok.
文本文件编码,文本文件有不同的存储方式,将字符串以什么样的形式保存为二进制,这个就是编码,UTF-8、ASCII、Unicode等,如果出现乱码一般就是编码的问题,文本文件相关的函数一般都有一个Encoding类型的参数,取得编码的方式:Encoding.Default、Encoding.UTF8、Encoding.GetEncoding(“GBK”)
文件编码(码表)
ASCII:英文码表,每个字符占1个字节。(正数)
GB2312:兼容ASCII,包含中文。每个英文占一个字节(正数),中文占两个字节(负数)
GBK:简体中文,兼容gb2312,包含更多汉字。英文占1个字节(正数),中文占两个(1个负数,1个可正可负)GB18030
Big5:繁体中文
Unicode:国际码表,中文英文都站2个字节。
UTF-8:国际码表,英文占1个字节,中文占3个字节。
输出Encoding.GetEncodings(),所有编码。
什么是文本文件。拖到记事本中还能看得懂的就是文本文件,doc不是。
(2)File类的常用静态方法:(FileInfo*)
void AppendAllText(string path, string contents),将文本contents附加到文件path中
bool Exists(string path)判断文件path是否存在
string[] ReadAllLines(string path) 读取文本文件到字符串数组中
string ReadAllText(string path) 读取文本文件到字符串中
void WriteAllText(string path, string contents)将文本contents保存到文件path中,会覆盖旧内容。
WriteAllLines(string path,string[] contents),将字符串数组逐行保存到文件path中,会覆盖旧内容。
(3)File类的方法1
File.Copy(“source”, “targetFileName”, true);//文件拷贝,true表示当文件存在时“覆盖”,如果不加true,则文件存在报异常。
File.Exists();//判断文件是否存在
File.Move(“source”, “target”);//移动(剪切),思考如何为文件重命名?文件的剪切是可以跨磁盘的。
File.Delete(“path”);//删除。如果文件不存在?不存在,不报错
File.Create(“path”);//创建文件
(4)File类的方法2:操作文本文件
File.ReadAllLines(“path”, Encoding.Default);//读取所有行,返回string[]
File.ReadAllText(“path”, Encoding.Default);//读取所有文本返回string
File.ReadAllBytes(“path”);//读取文件,返回byte[],把文件作为二进制来处理。
File.WriteAllLines(“path”, new string[4] ,Encoding.Default);//将string数组按行写入文件。
File.WriteAllText(“path”, “string”);//将字符串全部写入文件
File.WriteAllBytes(“path”,new byte[5]);//将byte[]全部写入到文件
File.AppendAllText()//将string追加到文件
(5)File类的方法3:
a.快速得到文件流
FileStream fs=File.Open(); //返回FileStream
FileStream fs=File.OpenRead();//返回只读的FileStream
FileStream fs=File.OpenWrite();//返回只写的FileStream
FileStream fs=new FileStream(参数);
Stream(所有流的父类,是一个抽象类。)
文件操作的类都在System.IO.*;
b.文件流
拷贝文件的两种方式:将源文件内容全部读到内存中,再写到目标文件中;读取源文件的1KB内存,写到目标文件中,再读取源文件的1KB内存,再写到目标文件中……。第二种方式就是一种流的操作。
用File.ReadAllText、File.WriteAllText进行文件读写是一次性读、写,如果文件非常大会占内存、慢。需要读一行处理一行的机制,这就是流(Stream)。Stream会只读取要求的位置、长度的内容。
Stream不会将所有内容一次性读取到内存中,有一个指针,指针指到哪里才能读、写到哪里。
流有很多种类,文件流是其中一种。FileStream类new FileStream(“c:/a.txt”, filemode, fileaccess)后两个参数可选值及含义自己看。 FileStream可读可写。可以使用File.OpenRead、File.OpenWrite这两个简化调用方法。
byte[]是任何数据的最根本表示形式,任何数据最终都是二进制。
FileStream的Position属性为当前文件指针位置,每写一次就要移动一下Position以备下次写到后面的位置。Write用于向当前位置写入若干字节,Read用户读取若干字节。(*)
c.使用FileStream写入文本文件。
演示通过FileStream写入读取文本文件。对于中文如果每次读取1个byte会有什么效果?更好的选择→StreamReader
d.使用FileStream读取文本文件。
e.使用FileStream进行大文件拷贝。
演示File.ReadAllBytes()与File.WriteAllBytes()进行文件拷贝。(查看内存使用情况)
使用using可以方便的释放资源(自动调用Dispose方法)
只有实现了IDispose接口的类才能使用using释放资源
f.文件加密(每一位用255-r)。加密就是解密,解密就是加密。(帮助理解文件流而已)
g.byte[]是任何数据的最根本表示形式,任何数据最终都是二进制。
使用using来简化操作。
总结:不是任何类型的对象都可以写在using()的小括号里面的
只有实现了IDisposable接口的类型的对象,才能写在using的小括号里面
当using{}执行完毕时,会自动调用对象的Dispose()方法来释放资源。
h.大文件拷贝。
FileStream的Position属性为当前文件指针位置,每写一次就要移动一下Position以备下次写到后面的位置。Write用于向当前位置写入若干字节,Read用户读取若干字节。(*)//可以手动设置获取该值。
Utf-8:前3个字节(*)
Unicode(utf-16)前2个字节。(*)
i. 写文本文件StreamWriter
Stream把所有内容当成二进制来看待,如果是文本内容,则需要程序员来处理文本和二进制之间的转换。
用StreamWriter可以简化文本类型的Stream的处理
StreamWriter是辅助Stream进行处理的
using (StreamWriter writer = new StreamWriter(stream, encoding))
{
writer.WriteLine(“你好”);
}
j. 读取文本文件StreamReader
和StreamWriter类似, StreamReader简化了文本类型的流的读取。
Stream stream = File.OpenRead(“c:/1.txt”);
using (StreamReader reader = new StreamReader(stream,encoding))
{
//Console.WriteLine(reader.ReadToEnd());
Console.WriteLine(reader.ReadLine());
}
ReadToEnd用于从当前位置一直读到最后,内容大的话会占内存;每次调用都往下走,不能无意中调用了两次
ReadLine读取一行,如果到了末尾,则返回null。
7、对象序列化(二进制序列化,格式化)
(1)对象序列化是将对象(比如Person对象)转换为二进制数据(字节流),反序列化是将二进制数据还原为对象。对象是稍纵即逝的,不仅程序重启、操作系统重启会造成对象的消失,就是退出函数范围等都可能造成对象的消失,序列化/反序列化就是为了保持对象的持久化。就像用DV录像(序列化)和用播放器播放(反序列化)一样。
对象序列化,只能针对对象的字段进行序列化。
(2)BinaryFormatter类有两个方法:
void Serialize(Stream stream, object graph)对象graph序列化到stream中
object Deserialize(Stream stream)将对象从stream中反序列化,返回值为反序列化得到的对象
(3)不是所有对象都能序列化,只有可序列化的对象才能序列化,在类声明上添加[Serializable],对象的属性、字段的类型也必须可序列化
(4)关于二进制序列化需要注意的事项:
a.要序列化的类型必须标记为:[Serializable]
b.该类型的父类也必须标记为: [Serializable]
c.该类型中的所有成员的类型也必须标记为: [Serializable]
d.序列化只会对类中的字段序列化。(只能序列化一些状态信息。)NonSerialized
e.不建议使用自动属性。(每次生成的字段都可能不一样,影响反序列化)
(5)为什么要序列化?
将一个复杂的对象转换流,方便我们的存储与信息交换
(6)序列化应用*
序列化的应用: ASP.Net ViewState、WCF、.Net Remoting、ASP.Net Cache 、集群等。
将对象持久化存储,磁盘、数据库
将对象复制到剪贴板
将对象通过网络传输
将对象备份(深拷贝。)
(7)序列化的步骤
1创建一个二进制序列化器:
BinaryFormatter bf=…..;
2创建一个文件流。
3bf.Serialize(stream,对象);
反序列化的步骤
4创建一个二进制序列化器:
BinaryFormatter bf;
5创建文件流:
6执行反序列化:
object obj=bf.Deserialize(stream);
(8)javascript序列化
(9)XML序列化

0 0