C#学习笔记 二进制输入输出

1.BinaryReader类和BinaryWriter类

BinaryReaderBinaryWriter可以用来进行二进制输入/输出,也就是用来读写基本的数据类型(如intdouble等),而不是原始的字节类型。BinaryReaderBinaryWriter不是Stream类的子类,但它是对Stream流进行包装,在构造BinaryReaderBinaryWriter对象时,需要一个Stream对象作为其参数。如:

	new BinaryReader(myStream);

实际上,这两种类主要是在基本类型和原始字节之间进行转换,因此它们需要处理能够对字节进行I/O的一些基本的Stream对象,如FileStream或者MemoryStream。这两种类都有一个BaseStream属性,通过该属性可以得到对基本的Stream对象的引用。以下是BinaryWriter类的一些方法:
在这里插入图片描述
BinaryReaderBinaryWriter有很相似的功能,有多个不同名字的ReadXXX()方法。例如,在BinaryWriter中可以有Write(Int16)方法和Write(Char)方法,而在BinaryReader中则只能有ReadInt16()方法和ReadChar()方法。因为,当执行写操作时,writer对象能够根据Write()的参数推断出写入的内容;而当执行读操作时,面对每一个字节流,reader对象并不知道应该如何把这些字节组织到一起。必须通过调用某个特定的函数,才能够告诉reader对象如何把字节流组织到一起。

2.用Stream流进行二进制输入/输出

BinaryReaderBinaryWriter可以对Stream进行包装,从而进行二进制的原始数据的输入/输出。
例,以二进制格式向文件中写入数据,然后再从该文件中读出数据:

using System;
using System.IO;
class Test
{
    
    
	static void Main(){
    
    
		try {
    
    
			FileStream ds = new FileStream("test_binary.dat", FileMode.Create, FileAccess.ReadWrite);

			BinaryWriter bw = new BinaryWriter(ds);

			// Write some data to the stream;
			bw.Write("A string");
			bw.Write(142);
			bw.Write(97.4);
			bw.Write(true);

			// Open it for reading;
			BinaryReader br = new BinaryReader(ds);

			// Move back to the start;
			br.BaseStream.Seek(0, SeekOrigin.Begin);

			// Read the data
			Console.WriteLine(br.ReadString());
			Console.WriteLine(br.ReadInt32());
			Console.WriteLine(br.ReadDouble());
			Console.WriteLine(br.ReadBoolean());

		} catch (Exception e) {
    
    

			Console.WriteLine("Exception:" + e.ToString());
		}	
	}
}

例中创建了一个FileStream对象,用来对文件进行操作。创建对象时的第二个参数确定文件以什么样的方式打开,在本例中,为FileMode.Create,表示要创建一个新的文件,或者覆盖已经存在的同名文件。第三个参数决定文件的访问权限,本例中用FileAccess.ReadWrite,要对文件进行读写操作。
FileStream可以对自己的进行操作,操作起来通常很不方便,因此FileStream经常被包装到其他能够对字节进行转换的类中使用。如上,使用了一个BinaryWriter类,该类能够接收.NET中的原始类型,并将其转换为字节。然后再把字节传送到FileStream类中。
程序中然后创建一个BinaryReader对象用来从FileStream中读取数据。在使用BinaryReader之前,必须首先退回到文件的开头,即调用Seek()对方法FileStream重新定位,然后从文件中读取数据。

3.使用File的二进制功能

.NET Framework提供了专门的File类来处理文件的相关功能,File是个工具类,是个static类,直接使用“File.方法”即可。
这些方法中,一类是得到一个流以方便操作,如File.Create(path)创建或打开一个FileStream,而File.OpenRead(path)则得到一个FileStream用于读,File.OpenWrite(path)则得到一个FileStream用于写。
另一类则更方便,打开、读写、关闭文件只有一个方法就行了,包括:

  • File. ReadAlIBytes(path)读到一个文件的所有字节,返回一个字节数组;
  • File. WriteAllBytes(path,bytes)写入字节数组到一个文件中;
  • File. Copy(path,path2)复制文件。

序列化与反序列化

1.什么是对象序列化

C#对象一般位于内存中,但在现实应用中常常要求在C#程序停止运行之后能够保存(持久化)指定的对象,并在将来重新读取被保存的对象。C#对象序列化(serialize)、反序列化(deserialize)就能够实现该功能。
使用对象序列化,将对象保存到磁盘或输出到网络时,会把其状态保存为一组字节,在未来再将这些字节组转成对象(反序列化)。除了在持久化对象时会用到对象序列化之外,当使用远程方法调用(如RemotingWebService等),或在网络中传递对象时,都会用到对象序列化。另外,也可以将一个对象序列化再反序列化可以得到一个对象的拷贝。

2.简单的序列化及反序列化

System.Runtime.Serialization命名空间提供了对象序列化和含序列化功能。只要一个类标记了[Serializable]这个特性(Attribute),那么它就可以被序列化。要进行序列化及反序列化操作,需要一个实现了IFormatter的对象,IFormatter具有Serialize(stream, object)Deserialize(stream)方法。.NET Framework中已经实现了下面几种IFormatter对象。

  • BinaryFormatter,二进制的格式,可将对象序列化成二进制信息,主要用于对象状态的保存(如游戏状态)、远程调用(Remoting),它的特点是效率较高,但只能在.NET Framework平台内反序列化。这要用到System.Runtime.Serialization.Formatters.Binary命名空间。
  • XMLDeserialize,XML的格式化,可将对象序列化成规范的XML信息,主要用于对象状态的保存和数据交换,它的特点是可以与其他平台的语言交换数据。要注意的是,这里不是用IFormatter,而是用System.XML.Serialization命名空间中的XmlSerializer类,它也具有Serialize()Deserialize()方法。
  • ③ SoapFormatter,SOAP是XML Web Service远程服务调用的一种格式,主要用于XML Web Service,在Visual Studio中有专门的工具来自动处理。

例,二进制及XML格式的序列化:

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;

[Serializable]
public class Person
{
    
    
	public string Name {
    
     get; set; }
	public int Age {
    
     get; set; }
	public Person() {
    
     }
	public Person(string name, int age) {
    
    
		this.Name = name;
		this.Age = age;
	}
	public override string ToString() {
    
    
		return Name + "(" + Age + ")";
	}
}

public class SerializeDemo
{
    
    
	public static void TestMain() {
    
    
		Person[] people = {
    
    
			new Person("李明", 18),
			new Person("王强", 19),
		};

		// 二进制序列化
		BinaryFormatter binary = new BinaryFormatter();
		string fileName = "s.temp";
		BinarySerialize(binary, fileName, people);

		// 二进制反序列化
		Person[] people1 = BinaryDeserialize(binary, fileName) as Person[];
		foreach (Person p in people1)
			Console.WriteLine(p);

		// XML序列化
		XmlSerializer xmlser = new XmlSerializer(typeof(Person[]));
		string xmlFileName = "s.xml";
		XmlSerializer(xmlser, xmlFileName, people);

		// 显示XML文本
		string xml = File.ReadAllText(xmlFileName);
		Console.WriteLine(xml);
	}

	private static void BinarySerialize(IFormatter formatter, string fileName, object obj) {
    
    
		FileStream fs = new FileStream(fileName, FileMode.Create);
		formatter.Serialize(fs, obj);
		fs.Close();
	}
	private static object BinaryDeserialize(IFormatter formatter, string fileName) {
    
    
		FileStream fs = new FileStream(fileName, FileMode.Open);
		object obj = formatter.Deserialize(fs);
		fs.Close();
		return obj;
	}
	private static void XmlSerializer(XmlSerializer ser, string fileName, object obj) {
    
    
		FileStream fs = new FileStream(fileName, FileMode.Create);
		ser.Serialize(fs, obj);
		fs.Close();
	}
}

运行结果:

李明(18)
王强(19)
<?xml version="1.0"?>
<ArrayOfPerson xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Person>
    <Name>李明</Name>
    <Age>18</Age>
  </Person>
  <Person>
    <Name>王强</Name>
    <Age>19</Age>
  </Person>
</ArrayOfPerson>

猜你喜欢

转载自blog.csdn.net/qq_45349225/article/details/114401197