🐋作者简介:博主是一位.Net开发者,同时也是RPA和低代码平台的践行者。
🐬个人主页: 会敲键盘的肘子
🐰系列专栏: .Net实用方法总结
🦀专栏简介:博主针对.Net开发和C站问答过程中遇到的问题进行总结,形成本专栏,希望可以帮助到您解决问题。
🐶座右铭:总有一天你所坚持的会反过来拥抱你。
🌈写在前面:本文主要介绍System.IO命名空间的BinaryReader 类,介绍其常用的方法和示例说明。
👉本文关键字:System.IO、BinaryReader类、方法示例、C#
[TOC]
1️⃣ System.IO命名空间
.NET中的IO操作命名空间,包含允许读写文件和数据流的类型以及提供基本文件和目录支持的类型。
我们在.NET中的IO操作,经常需要调用一下几个类。
- FileStream类
文件流类,负责大文件的拷贝,读写。
- Path类
Path类中方法,基本都是对字符串(文件名)的操作,与实际文件没多大关系。
- File类
File类可以进行一些对小文件拷贝、剪切操作,还能读一些文档文件。
- Dirctory类
目录操作,创建文件、删除目录,获取目录下文件名等等。
2️⃣ BinaryReader类
♈ 定义
用特定的编码将基元数据类型读作二进制值。
public class BinaryReader : IDisposable
示例
下面的代码示例演示如何在文件中存储和检索应用程序设置。
using System;
using System.IO;
using System.Text;
class ConsoleApplication
{
const string fileName = "AppSettings.dat";
static void Main()
{
WriteDefaultValues();
DisplayValues();
}
public static void WriteDefaultValues()
{
using (var stream = File.Open(fileName, FileMode.Create))
{
using (var writer = new BinaryWriter(stream, Encoding.UTF8, false))
{
writer.Write(1.250F);
writer.Write(@"c:\Temp");
writer.Write(10);
writer.Write(true);
}
}
}
public static void DisplayValues()
{
float aspectRatio;
string tempDirectory;
int autoSaveTime;
bool showStatusBar;
if (File.Exists(fileName))
{
using (var stream = File.Open(fileName, FileMode.Open))
{
using (var reader = new BinaryReader(stream, Encoding.UTF8, false))
{
aspectRatio = reader.ReadSingle();
tempDirectory = reader.ReadString();
autoSaveTime = reader.ReadInt32();
showStatusBar = reader.ReadBoolean();
}
}
Console.WriteLine("Aspect ratio set to: " + aspectRatio);
Console.WriteLine("Temp directory is: " + tempDirectory);
Console.WriteLine("Auto save time set to: " + autoSaveTime);
Console.WriteLine("Show status bar: " + showStatusBar);
}
}
}
此类型实现 IDisposable 接口。 使用从此类型派生的任何类型后,应直接或间接释放它。 若要直接释放类型,请在try
/catch
块中调用其 Dispose 方法。 若要间接释放类型,请使用using
(在 C# 中)或Using
(在 Visual Basic 中)等语言构造。 有关详细信息,请参阅接口主题中的 IDisposable Dispose 和“使用实现 IDisposable 的对象”部分。
♌ 常用方法
Close() 关闭
public virtual void Close ();
注意:此方法调用 Dispose ,指定true
以释放所有资源。 不需要专门调用 Close 方法。 请确保 Stream 已正确释放每个对象。 可以 Streamusing
Using
在 Visual Basic) 中 (或块中声明对象,以确保释放流及其所有资源,或者可以显式调用 Dispose 方法。
Dispose() 释放
public void Dispose ();
FillBuffer(Int32) 用从流中读取的指定字节数填充内部缓冲区
protected virtual void FillBuffer (int numBytes);
Read(Char[], Int32, Int32) 从字符数组中的指定点开始,从流中读取指定的字符数
public virtual int Read (char[] buffer, int index, int count);
参数
buffer
Char[]
当此方法返回时,包含指定的字符数组,此数组中
index
和 (index
+count
- 1) 之间的值被从当前源中读取的字符所替换。
index
在
buffer
中开始写入的位置。
count
最多读取的字符数。 如果在将指定数量的字符读入缓冲区之前就已达读取器的末尾,则返回该方法。
返回
Int32已读取的字符数。 该数会小于或等于
count
,具体取决于读取器中是否有可用的数据。 如果调用此方法时没有留下更多的字符供读取,则此方法返回 0(零)。
示例
以下示例演示如何使用内存作为后盾存储来读取和写入数据。 此示例显示控制台的文件路径字符无效的列表。 尽管代码尝试显示所有无效文件路径字符的列表,但并非所有字符都位于可显示字符集中。 由于无效字符列表可能因系统而异,因此此代码的输出也可能有所不同。
using System;
using System.IO;
class BinaryRW
{
static void Main()
{
char[] invalidPathChars = Path.InvalidPathChars;
MemoryStream memStream = new MemoryStream();
BinaryWriter binWriter = new BinaryWriter(memStream);
// Write to memory.
binWriter.Write("Invalid file path characters are: ");
binWriter.Write(
Path.InvalidPathChars, 0, Path.InvalidPathChars.Length);
// Create the reader using the same MemoryStream
// as used with the writer.
BinaryReader binReader = new BinaryReader(memStream);
// Set Position to the beginning of the stream.
memStream.Position = 0;
// Read the data from memory and write it to the console.
Console.Write(binReader.ReadString());
int arraySize = (int)(memStream.Length - memStream.Position);
char[] memoryData = new char[arraySize];
binReader.Read(memoryData, 0, arraySize);
Console.WriteLine(memoryData);
}
}
Read(Byte[], Int32, Int32) 从字节数组中的指定点开始,从流中读取指定的字节数
public virtual int Read (byte[] buffer, int index, int count);
参数
buffer
Byte[]
当此方法返回时,包含指定的字符数组,此数组中
index
和 (index
+count
- 1) 之间的值被从当前源中读取的字符所替换。
index
在
buffer
中开始写入的位置。
count
最多读取的字符数。 如果在将指定数量的字符读入缓冲区之前就已达读取器的末尾,则返回该方法。
返回
Int32已读取的字符数。 该数会小于或等于
count
,具体取决于读取器中是否有可用的数据。 如果调用此方法时没有留下更多的字符供读取,则此方法返回 0(零)。
示例
以下示例演示如何使用内存作为后盾存储来写入二进制数据。 它向控制台显示一条消息,指示数据是否已正确写入。
using System;
using System.IO;
namespace BinaryRW
{
class Program
{
static void Main(string[] args)
{
const int arrayLength = 1000;
byte[] dataArray = new byte[arrayLength];
byte[] verifyArray = new byte[arrayLength];
new Random().NextBytes(dataArray);
using (BinaryWriter binWriter = new BinaryWriter(new MemoryStream()))
{
Console.WriteLine("Writing the data.");
binWriter.Write(dataArray, 0, arrayLength);
using (BinaryReader binReader = new BinaryReader(binWriter.BaseStream))
{
binReader.BaseStream.Position = 0;
if (binReader.Read(verifyArray, 0, arrayLength) != arrayLength)
{
Console.WriteLine("Error writing the data.");
return;
}
}
}
for (int i = 0; i < arrayLength; i++)
{
if (verifyArray[i] != dataArray[i])
{
Console.WriteLine("Error writing the data.");
return;
}
}
Console.WriteLine("The data was written and verified.");
}
}
}
此示例读取文件的内容,并以 16 列格式显示每个字节的数值。 当方法返回零字节时 Read ,检测到正在读取的文件的末尾。
using System;
using System.IO;
using System.Text;
public class DumpFileSample
{
private static readonly int CHUNK_SIZE = 1024;
public static void Main(String[] args)
{
if ((args.Length == 0) || !File.Exists(args[0]))
{
Console.WriteLine("Please provide an existing file name.");
}
else
{
using (FileStream fs = new FileStream(args[0], FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()))
{
byte[] chunk;
chunk = br.ReadBytes(CHUNK_SIZE);
while(chunk.Length > 0)
{
DumpBytes(chunk, chunk.Length);
chunk = br.ReadBytes(CHUNK_SIZE);
}
}
}
}
}
public static void DumpBytes(byte[] bdata, int len)
{
int i;
int j = 0;
char dchar;
// 3 * 16 chars for hex display, 16 chars for text and 8 chars
// for the 'gutter' int the middle.
StringBuilder dumptext = new StringBuilder(" ", 16 * 4 + 8);
for (i = 0; i < len; i++)
{
dumptext.Insert(j * 3, String.Format("{0:X2} ", (int)bdata[i]));
dchar = (char)bdata[i];
//' replace 'non-printable' chars with a '.'.
if (Char.IsWhiteSpace(dchar) || Char.IsControl(dchar))
{
dchar = '.';
}
dumptext.Append(dchar);
j++;
if (j == 16)
{
Console.WriteLine(dumptext);
dumptext.Length = 0;
dumptext.Append(" ");
j = 0;
}
}
// display the remaining line
if (j > 0)
{
for (i = j; i < 16; i++)
{
dumptext.Insert(j * 3, " ");
}
Console.WriteLine(dumptext);
}
}
}
BinaryReader 在读取操作失败后,不会还原文件位置。
ReadBoolean() 从当前流中读取 Boolean
值,并使该流的当前位置提升 1 个字节
public virtual bool ReadBoolean ();
返回
Boolean如果字节为非零则为
true
,否则为false
。
示例
下面的代码示例演示如何在文件中存储和检索应用程序设置。
using System;
using System.IO;
using System.Text;
class ConsoleApplication
{
const string fileName = "AppSettings.dat";
static void Main()
{
WriteDefaultValues();
DisplayValues();
}
public static void WriteDefaultValues()
{
using (var stream = File.Open(fileName, FileMode.Create))
{
using (var writer = new BinaryWriter(stream, Encoding.UTF8, false))
{
writer.Write(1.250F);
writer.Write(@"c:\Temp");
writer.Write(10);
writer.Write(true);
}
}
}
public static void DisplayValues()
{
float aspectRatio;
string tempDirectory;
int autoSaveTime;
bool showStatusBar;
if (File.Exists(fileName))
{
using (var stream = File.Open(fileName, FileMode.Open))
{
using (var reader = new BinaryReader(stream, Encoding.UTF8, false))
{
aspectRatio = reader.ReadSingle();
tempDirectory = reader.ReadString();
autoSaveTime = reader.ReadInt32();
showStatusBar = reader.ReadBoolean();
}
}
Console.WriteLine("Aspect ratio set to: " + aspectRatio);
Console.WriteLine("Temp directory is: " + tempDirectory);
Console.WriteLine("Auto save time set to: " + autoSaveTime);
Console.WriteLine("Show status bar: " + showStatusBar);
}
}
}
ReadByte() 从当前流中读取下一个字节,并使流的当前位置提升 1 个字节
public virtual byte ReadByte ();
返回
Byte从当前流中读取的下一个字节。
示例
下面的代码示例演示如何使用内存编写二进制数据作为后盾存储,然后验证数据是否已正确写入。
using System;
using System.IO;
class BinaryRW
{
static void Main()
{
int i = 0;
// Create random data to write to the stream.
byte[] writeArray = new byte[1000];
new Random().NextBytes(writeArray);
BinaryWriter binWriter = new BinaryWriter(new MemoryStream());
BinaryReader binReader =
new BinaryReader(binWriter.BaseStream);
try
{
// Write the data to the stream.
Console.WriteLine("Writing the data.");
for(i = 0; i < writeArray.Length; i++)
{
binWriter.Write(writeArray[i]);
}
// Set the stream position to the beginning of the stream.
binReader.BaseStream.Position = 0;
// Read and verify the data from the stream.
for(i = 0; i < writeArray.Length; i++)
{
if(binReader.ReadByte() != writeArray[i])
{
Console.WriteLine("Error writing the data.");
return;
}
}
Console.WriteLine("The data was written and verified.");
}
// Catch the EndOfStreamException and write an error message.
catch(EndOfStreamException e)
{
Console.WriteLine("Error writing the data.\n{0}",
e.GetType().Name);
}
}
}
ReadBytes(Int32) 从当前流中读取指定的字节数以写入字节数组中,并将当前位置前移相应的字节数
public virtual byte[] ReadBytes (int count);
参数
count
要读取的字节数。 此值必须为 0 或非负数字,否则将出现异常。
返回
Byte从当前流中读取的下一个字节。
示例
下面的代码示例演示如何使用内存编写二进制数据作为后盾存储,然后验证数据是否已正确写入。
using System;
using System.IO;
class BinaryRW
{
static void Main()
{
int i = 0;
// Create random data to write to the stream.
byte[] writeArray = new byte[1000];
new Random().NextBytes(writeArray);
BinaryWriter binWriter = new BinaryWriter(new MemoryStream());
BinaryReader binReader =
new BinaryReader(binWriter.BaseStream);
try
{
// Write the data to the stream.
Console.WriteLine("Writing the data.");
for(i = 0; i < writeArray.Length; i++)
{
binWriter.Write(writeArray[i]);
}
// Set the stream position to the beginning of the stream.
binReader.BaseStream.Position = 0;
// Read and verify the data from the stream.
for(i = 0; i < writeArray.Length; i++)
{
if(binReader.ReadByte() != writeArray[i])
{
Console.WriteLine("Error writing the data.");
return;
}
}
Console.WriteLine("The data was written and verified.");
}
// Catch the EndOfStreamException and write an error message.
catch(EndOfStreamException e)
{
Console.WriteLine("Error writing the data.\n{0}",
e.GetType().Name);
}
}
}
此示例读取文件的内容,并将其作为转储文本显示在控制台中。 当从ReadBytes零返回的数组长度时,将检测到正在读取的文件的Byte末尾。
using System;
using System.IO;
using System.Text;
public class DumpFileSample
{
private static readonly int CHUNK_SIZE = 1024;
public static void Main(String[] args)
{
if ((args.Length == 0) || !File.Exists(args[0]))
{
Console.WriteLine("Please provide an existing file name.");
}
else
{
using (FileStream fs = new FileStream(args[0], FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()))
{
byte[] chunk;
chunk = br.ReadBytes(CHUNK_SIZE);
while(chunk.Length > 0)
{
DumpBytes(chunk, chunk.Length);
chunk = br.ReadBytes(CHUNK_SIZE);
}
}
}
}
}
public static void DumpBytes(byte[] bdata, int len)
{
int i;
int j = 0;
char dchar;
// 3 * 16 chars for hex display, 16 chars for text and 8 chars
// for the 'gutter' int the middle.
StringBuilder dumptext = new StringBuilder(" ", 16 * 4 + 8);
for (i = 0; i < len; i++)
{
dumptext.Insert(j * 3, String.Format("{0:X2} ", (int)bdata[i]));
dchar = (char)bdata[i];
//' replace 'non-printable' chars with a '.'.
if (Char.IsWhiteSpace(dchar) || Char.IsControl(dchar))
{
dchar = '.';
}
dumptext.Append(dchar);
j++;
if (j == 16)
{
Console.WriteLine(dumptext);
dumptext.Length = 0;
dumptext.Append(" ");
j = 0;
}
}
// display the remaining line
if (j > 0)
{
for (i = j; i < 16; i++)
{
dumptext.Insert(j * 3, " ");
}
Console.WriteLine(dumptext);
}
}
}
ReadChar() 从当前流中读取下一个字符,并根据所使用的 Encoding
和从流中读取的特定字符,提升流的当前位置
public virtual char ReadChar ();
返回
Char从当前流中读取的字符。
示例
下面的代码示例演示如何使用内存作为后盾存储来读取和写入数据。
using System;
using System.IO;
class BinaryRW
{
static void Main()
{
int i = 0;
char[] invalidPathChars = Path.InvalidPathChars;
MemoryStream memStream = new MemoryStream();
BinaryWriter binWriter = new BinaryWriter(memStream);
// Write to memory.
binWriter.Write("Invalid file path characters are: ");
for(i = 0; i < invalidPathChars.Length; i++)
{
binWriter.Write(invalidPathChars[i]);
}
// Create the reader using the same MemoryStream
// as used with the writer.
BinaryReader binReader = new BinaryReader(memStream);
// Set Position to the beginning of the stream.
memStream.Position = 0;
// Read the data from memory and write it to the console.
Console.Write(binReader.ReadString());
char[] memoryData =
new char[memStream.Length - memStream.Position];
for(i = 0; i < memoryData.Length; i++)
{
memoryData[i] = binReader.ReadChar();
}
Console.WriteLine(memoryData);
}
}
ReadChars(Int32) 从当前流中读取指定的字符数,并以字符数组的形式返回数据,然后根据所使用的 Encoding
和从流中读取的特定字符,将当前位置前移
public virtual char[] ReadChars (int count);
参数
count
要读取的字符数。
返回
Char[]包含从基础流中读取的数据的字节数组。 如果到达了流的末尾,则该字符数组可能小于所请求的字符数。
示例
下面的代码示例演示如何使用内存作为后盾存储来读取和写入数据。
using System;
using System.IO;
class BinaryRW
{
static void Main()
{
char[] invalidPathChars = Path.InvalidPathChars;
MemoryStream memStream = new MemoryStream();
BinaryWriter binWriter = new BinaryWriter(memStream);
// Write to memory.
binWriter.Write("Invalid file path characters are: ");
binWriter.Write(Path.InvalidPathChars);
// Create the reader using the same MemoryStream
// as used with the writer.
BinaryReader binReader = new BinaryReader(memStream);
// Set Position to the beginning of the stream.
memStream.Position = 0;
// Read the data from memory and write it to the console.
Console.Write(binReader.ReadString());
Console.WriteLine(binReader.ReadChars(
(int)(memStream.Length - memStream.Position)));
}
}
ReadDouble() 从当前流中读取 8 字节浮点值,并使流的当前位置提升 8 个字节
public virtual double ReadDouble ();
返回
Double从当前流中读取的 8 字节浮点值。
示例
下面的代码示例演示如何使用类顶部MemoryStream的BinaryReader
类BinaryWriter读取和写入Double
内存中的数据。 MemoryStream
仅读取和写入 Byte
数据。
using System;
using System.IO;
class BinaryRW
{
static void Main()
{
int i;
const int arrayLength = 1000;
// Create random data to write to the stream.
Random randomGenerator = new Random();
double[] dataArray = new double[arrayLength];
for(i = 0; i < arrayLength; i++)
{
dataArray[i] = 100.1 * randomGenerator.NextDouble();
}
using(BinaryWriter binWriter =
new BinaryWriter(new MemoryStream()))
{
// Write the data to the stream.
Console.WriteLine("Writing data to the stream.");
for(i = 0; i < arrayLength; i++)
{
binWriter.Write(dataArray[i]);
}
// Create a reader using the stream from the writer.
using(BinaryReader binReader =
new BinaryReader(binWriter.BaseStream))
{
try
{
// Return to the beginning of the stream.
binReader.BaseStream.Position = 0;
// Read and verify the data.
Console.WriteLine("Verifying the written data.");
for(i = 0; i < arrayLength; i++)
{
if(binReader.ReadDouble() != dataArray[i])
{
Console.WriteLine("Error writing data.");
break;
}
}
Console.WriteLine("The data was written " +
"and verified.");
}
catch(EndOfStreamException e)
{
Console.WriteLine("Error writing data: {0}.",
e.GetType().Name);
}
}
}
}
}
ReadInt32() 从当前流中读取 4 字节有符号整数,并使流的当前位置提升 4 个字节
public virtual int ReadInt32 ();
返回
Int32从当前流中读取的 2 字节有符号整数。
示例
下面的代码示例演示如何在文件中存储和检索应用程序设置。
using System;
using System.IO;
using System.Text;
class ConsoleApplication
{
const string fileName = "AppSettings.dat";
static void Main()
{
WriteDefaultValues();
DisplayValues();
}
public static void WriteDefaultValues()
{
using (var stream = File.Open(fileName, FileMode.Create))
{
using (var writer = new BinaryWriter(stream, Encoding.UTF8, false))
{
writer.Write(1.250F);
writer.Write(@"c:\Temp");
writer.Write(10);
writer.Write(true);
}
}
}
public static void DisplayValues()
{
float aspectRatio;
string tempDirectory;
int autoSaveTime;
bool showStatusBar;
if (File.Exists(fileName))
{
using (var stream = File.Open(fileName, FileMode.Open))
{
using (var reader = new BinaryReader(stream, Encoding.UTF8, false))
{
aspectRatio = reader.ReadSingle();
tempDirectory = reader.ReadString();
autoSaveTime = reader.ReadInt32();
showStatusBar = reader.ReadBoolean();
}
}
Console.WriteLine("Aspect ratio set to: " + aspectRatio);
Console.WriteLine("Temp directory is: " + tempDirectory);
Console.WriteLine("Auto save time set to: " + autoSaveTime);
Console.WriteLine("Show status bar: " + showStatusBar);
}
}
}
ReadSingle() 从当前流中读取 4 字节浮点值,并使流的当前位置提升 4 个字节
public virtual float ReadSingle ();
返回
Single从当前流中读取的 4 字节浮点值。
示例
下面的代码示例演示如何在文件中存储和检索应用程序设置。
using System;
using System.IO;
using System.Text;
class ConsoleApplication
{
const string fileName = "AppSettings.dat";
static void Main()
{
WriteDefaultValues();
DisplayValues();
}
public static void WriteDefaultValues()
{
using (var stream = File.Open(fileName, FileMode.Create))
{
using (var writer = new BinaryWriter(stream, Encoding.UTF8, false))
{
writer.Write(1.250F);
writer.Write(@"c:\Temp");
writer.Write(10);
writer.Write(true);
}
}
}
public static void DisplayValues()
{
float aspectRatio;
string tempDirectory;
int autoSaveTime;
bool showStatusBar;
if (File.Exists(fileName))
{
using (var stream = File.Open(fileName, FileMode.Open))
{
using (var reader = new BinaryReader(stream, Encoding.UTF8, false))
{
aspectRatio = reader.ReadSingle();
tempDirectory = reader.ReadString();
autoSaveTime = reader.ReadInt32();
showStatusBar = reader.ReadBoolean();
}
}
Console.WriteLine("Aspect ratio set to: " + aspectRatio);
Console.WriteLine("Temp directory is: " + tempDirectory);
Console.WriteLine("Auto save time set to: " + autoSaveTime);
Console.WriteLine("Show status bar: " + showStatusBar);
}
}
}
ReadString() 从当前流中读取一个字符串。 字符串有长度前缀,一次 7 位地被编码为整数
public virtual string ReadString ();
返回
String正被读取的字符串。
示例
下面的代码示例演示如何在文件中存储和检索应用程序设置。
using System;
using System.IO;
using System.Text;
class ConsoleApplication
{
const string fileName = "AppSettings.dat";
static void Main()
{
WriteDefaultValues();
DisplayValues();
}
public static void WriteDefaultValues()
{
using (var stream = File.Open(fileName, FileMode.Create))
{
using (var writer = new BinaryWriter(stream, Encoding.UTF8, false))
{
writer.Write(1.250F);
writer.Write(@"c:\Temp");
writer.Write(10);
writer.Write(true);
}
}
}
public static void DisplayValues()
{
float aspectRatio;
string tempDirectory;
int autoSaveTime;
bool showStatusBar;
if (File.Exists(fileName))
{
using (var stream = File.Open(fileName, FileMode.Open))
{
using (var reader = new BinaryReader(stream, Encoding.UTF8, false))
{
aspectRatio = reader.ReadSingle();
tempDirectory = reader.ReadString();
autoSaveTime = reader.ReadInt32();
showStatusBar = reader.ReadBoolean();
}
}
Console.WriteLine("Aspect ratio set to: " + aspectRatio);
Console.WriteLine("Temp directory is: " + tempDirectory);
Console.WriteLine("Auto save time set to: " + autoSaveTime);
Console.WriteLine("Show status bar: " + showStatusBar);
}
}
}
♎ 更多方法
更多方法请查阅官方文档 BinaryReader类。
⭐写在结尾:文章中出现的任何错误请大家批评指出,一定及时修改。
希望写在这里的小伙伴能给个三连支持!