C#中流的读取器和编写器(BinaryReader与 BinaryWriter ,StreamReader 与 StreamWriter,StringReader 等)详细介绍
智能建造小硕 硕士研究生在读,分享编程、人工智能、智能建造、学习和科研经验C#进阶笔记系列,帮助您强化C#基础,资料整理不易,欢迎关注交流!
通常,流用于字节输入和输出。 读取器和编写器类型处理编码字符与字节之间的来回转换,以便流可以完成操作。
下面是一些常用的读取器和编写器类:
- BinaryReader和 BinaryWriter :用于将基元数据类型作为二进制值进行读取和写入。
- StreamReader 和 StreamWriter : 用于通过使用编码值在字符和字节之间来回转换来读取和写入字符。
- StringReader 和 StringWriter:用于从字符串读取字符以及将字符写入字符串中。
- TextReader和 TextWriter :用作其他读取器和编写器(读取和写入字符和字符串,而不是二进制数据)的抽象基类。
1 先了解一下字符与字节
字节(Byte)是计量单位,表示数据量多少,是计算机信息技术用于计量存储容量的一种计量单位,通常情况下一字节(Byte)等于八位(bit)。
字符(Character)计算机中使用的字母、数字、字和符号,比如'A'、'B'、'$'、'&'等。
一般在英文状态下一个字母或字符占用一个字节,一个汉字用两个字节表示。
字节和字符(图片来源网络)字节与字符:
- ASCII 码中,一个英文字母(不分大小写)为一个字节,一个中文汉字为两个字节。
- UTF-8 编码中,一个英文字为一个字节,一个中文为三个字节。
- Unicode 编码中,一个英文为一个字节,一个中文为两个字节。
- 符号:英文标点为一个字节,中文标点为两个字节。例如:英文句号 . 占1个字节的大小,中文句号 。占2个字节的大小。
- UTF-16 编码中,一个英文字母字符或一个汉字字符存储都需要 2 个字节(Unicode 扩展区的一些汉字存储需要 4 个字节)。
- UTF-32 编码中,世界上任何字符的存储都需要 4 个字节。
2 BinaryReader 和BinaryWriter
2.1 BinaryReader
用特定的编码将基元数据类型读作二进制值。
2.1.1 常用构造方法和方法
构造方法和方法 | 描述 |
BinaryReader(Stream, Encoding, Boolean) | 基于所提供的流和特定的字符编码,初始化 BinaryReader 类的新实例,有选择性的打开流。Boolean:如果在释放 BinaryReader对象后保持流处于打开状态,则为 true;否则为 false。 |
Close() | 关闭当前阅读器及基础流 |
Dispose(Boolean) | 释放 BinaryReader类使用的非托管资源,并可以选择释放托管资源。 |
PeekChar() | 返回下一个可用的字符,并且不提升字节或字符的位置。如果没有可用字符或者流不支持查找时为 -1 |
Read() | 从基础流中读取字符,并根据所使用的 Encoding 和从流中读取的特定字符,提升流的当前位置。 |
Read(Span) | 从当前流读取字节序列,并将流中的位置向前移动读取的字节数。 |
ReadChar(int32) | 从当前流中读取指定的字符数,并以字符数组的形式返回数据,然后根据所使用的 Encoding 和从流中读取的特定字符,将当前位置前移。int32:要读取的字符数。 |
ReadString() | 从当前流中读取一个字符串。 字符串有长度前缀,一次 7 位地被编码为整数。 |
ReadBytes(Int32) | 从当前流中读取指定的字节数以写入字节数组中,并将当前位置前移相应的字节数。 |
BaseStream | 获取 BinaryWriter 的基础流。 |
2.1.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))
{//新建一个输入流,并以UTF-8编码,释放BinaryWriter后关闭流
using (var writer = new BinaryWriter(stream, Encoding.UTF8, false))
{//写入数据
writer.Write(1.250F);
writer.Write(3.657F);
writer.Write(@"c:\Temp");
writer.Write(10);
writer.Write(true);
}
}
}
public static void DisplayValues()//读取数据
{
float aspectRatio1;
float aspectRatio2;
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))
{
aspectRatio1 = reader.ReadSingle();//从当前流中读取 4 字节浮点值
aspectRatio2 = reader.ReadSingle();//从当前流中读取 4 字节浮点值
tempDirectory = reader.ReadString();//从当前流中读取一个字符串。
autoSaveTime = reader.ReadInt32();
showStatusBar = reader.ReadBoolean();
}
}
Console.WriteLine("Aspect ratio1 set to: " + aspectRatio1);
Console.WriteLine("Aspect ratio2 set to: " + aspectRatio2);
Console.WriteLine("Temp directory is: " + tempDirectory);
Console.WriteLine("Auto save time set to: " + autoSaveTime);
Console.WriteLine("Show status bar: " + showStatusBar);
}
}
}
运行结果
Aspect ratio1 set to: 1.25
Aspect ratio2 set to: 3.657
Temp directory is: c:\Temp
Auto save time set to: 10
Show status bar: True
2.2 BinaryWriter
将二进制中的基元类型写入流并支持用特定的编码写入字符串。
2.2.1 常用构造方法和方法
构造方法和方法 | 描述 |
BinaryWriter(Stream, Encoding, Boolean) | 基于所提供的流和特定的字符编码,初始化 BinaryWriter 类的新实例,有选择性的打开流。Boolean:如果在释放 BinaryReader对象后保持流处于打开状态,则为 true;否则为 false。 |
Close() | 关闭当前阅读器及基础流 |
Dispose(Boolean) | 释放 BinaryWriter类使用的非托管资源,并可以选择释放托管资源。 |
Flush() | 清理当前编写器的所有缓冲区,使所有缓冲数据写入基础设备。 |
Seek(Int32, SeekOrigin) | 设置当前流中的位置。 |
Write(Double) | 将 8 字节浮点值写入当前流,并将流的位置提升 8 个字节。 |
Write(String) | 将有长度前缀的字符串按 BinaryWriter 的当前编码写入此流,并根据所使用的编码和写入流的特定字符,提升流的当前位置。 |
Write(Char[], Int32, Int32) | 将字符数组部分写入当前流,并根据所使用的 Encoding(可能还根据向流中写入的特定字符),提升流的当前位置。Char[]:包含要写入的数据的字符数组。第一个Int32:要从 chars 中读取且要写入流的第一个字符的索引。第二个int32:要从 chars 中读取且要写入流的字符数。 |
Write(Byte[], Int32, Int32) | 将字节数组区域写入当前流。 |
Write(Boolean) | 将单字节 Boolean 值写入当前流,其中 0 表示 false,1 表示 true。 |
2.2.2代码示例
static void Main()
{
char[] nemechar = "智能建造小硕".ToCharArray();
MemoryStream memStream = new MemoryStream();
BinaryWriter binWriter = new BinaryWriter(memStream);
//写入内存
binWriter.Write("微信公众号的名字为: ");
binWriter.Write( nemechar, 0, nemechar.Length);
//读取内存
BinaryReader binReader = new BinaryReader(memStream);
// 设置当前MemoryStream的开始指针
memStream.Position = 0;
// 在控制打印出来
Console.Write(binReader.ReadString());
int arraySize = (int)(memStream.Length - memStream.Position);
char[] memoryData = new char[arraySize];
binReader.Read(memoryData, 0, arraySize);
Console.WriteLine(memoryData);
Console.WriteLine("名字长度"+memStream.Length);
Console.WriteLine("读取完后指针的当前位置"+memStream.Position);
binWriter.Close();
binReader.Close();
Console.WriteLine("".PadLeft(40,'-'));
const int arrayLength = 1000;
byte[] dataArray = new byte[arrayLength];
byte[] verifyArray = new byte[arrayLength];
new Random().NextBytes(dataArray);//随机产生字节数组
using (BinaryWriter binWriter1 = new BinaryWriter(new MemoryStream()))
{
Console.WriteLine("写入数据");
binWriter1.Write(dataArray, 0, arrayLength);
using (BinaryReader binReader1 = new BinaryReader(binWriter1.BaseStream))
//BaseStream就是操作streamreader的,返回的结果就是streamreader
{
binReader1.BaseStream.Position = 0;
if (binReader1.Read(verifyArray, 0, arrayLength) != arrayLength)//写入先后数据的长度是否相等
{
Console.WriteLine("错误写入数据");
return;//退出运行
}
}
}
for (int i = 0; i < arrayLength; i++)
{//读取前后的两个数据是否一样
if (verifyArray[i] != dataArray[i])
{
Console.WriteLine("错误写入数据");
return;
}
}
Console.WriteLine("数据被写入并验证");
}
运行结果:
微信公众号的名字为: 智能建造小硕
名字长度48
读取完后指针的当前位置48
----------------------------------------
写入数据
数据被写入并验证
3 StreamReader 和 StreamWriter
3.1 StreamReader
实现一个 TextReader,使其以一种特定的编码从字节流中读取字符。
StreamReader 默认为 UTF-8 编码,除非另有指定,而不是默认为当前系统的 ANSI 代码页。 UTF-8 正确处理 Unicode 字符,并针对操作系统的本地化版本提供一致的结果。
3.1.1 常用属性和方法
构造方法和方法 | 描述 |
StreamReader(Stream, Encoding, Boolean, Int32, Boolean) | 为指定的流初始化 StreamReader 类的新实例,带有指定的字符编码、字节顺序标记检测选项和缓冲区大小,有选择性的打开流。Boolean:如果要在文件开头查找字节顺序标记,则为true ;否则为 false。Int32:最小缓冲区大小。Boolean:如果在释放 StreamReader对象后保持流处于打开状态,则为 true;否则为 false。 |
StreamReader(String, Encoding, Boolean, Int32) | 为指定的文件名初始化 StreamReader类的新实例,带有指定字符编码、字节顺序标记检测选项和缓冲区大小。 |
BaseStream | 返回基础流。 |
CurrentEncoding | 获取当前 StreamReader对象正在使用的当前字符编码。 |
Close() | 关闭 StreamReader对象和基础流,并释放与读取器关联的所有系统资源。 |
Read(Char[], Int32, Int32) | 从指定的索引位置开始将来自当前流的指定的最多字符读到缓冲区。第一个Int32;开始写入的 buffer 的索引。第二个Int32:最多读取的字符数。 |
ReadLine() | 从当前流中读取一行字符并将数据作为字符串返回。 |
Dispose() | 释放由 TextReader对象使用的所有资源。 |
ReadToEnd() | 读取来自流的当前位置到结尾的所有字符。 |
3.1.2 代码示例
public static void Main()
{
try
{ //创建一个StreamReader实例读取文件
using (StreamReader sr = new StreamReader("G:\\Desktop\\archive1\\MyTest.txt"))
{
string line;
//一行行读取文件并在控制台输出
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
MemoryStream ms = new MemoryStream();
StreamWriter streamWriter = new StreamWriter(ms);
streamWriter.Write("智能建造小硕\n");
streamWriter.Flush();
ms.Position = 0;
StreamReader streamReader = new StreamReader(ms);
Console.WriteLine(streamReader.EndOfStream);
String rs =streamReader.ReadLine();
Console.WriteLine(rs);
}
catch (Exception e)
{
Console.WriteLine("不可读");
Console.WriteLine(e.Message);
}
}
运行结果
This is some textThis is some more text,
and this is on a new line
The following is a subset of characters:
123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{
False
智能建造小硕
3.2 StreamWriter
实现一个 TextWriter,使其以一种特定的编码向流中写入字符。
3.2.1 常用属性和方法
构造方法和方法 | 描述 |
StreamWriter(Stream, Encoding, Boolean, Int32, Boolean) | 使用指定的编码和缓冲区大小,为指定的流初始化 StreamWriter 类的新实例,并可以选择保持流处于打开状态。Boolean:如果要在文件开头查找字节顺序标记,则为true ;否则为 false。Int32:最小缓冲区大小。Boolean:如果在释放 StreamReader对象后保持流处于打开状态,则为 true;否则为 false。 |
StreamWriter(String, Encoding, FileStreamOptions) | 使用指定的编码并配置指定的 对象,为指定文件初始化 StreamWriter 类的新 FileStreamOptions实例。String:要写入的完整文件路径。 |
BaseStream | 返回基础流。 |
Encoding | 获取在其中写入输出的 Encoding |
Close() | 关闭 StreamWriter对象和基础流,并释放与读取器关联的所有系统资源。 |
Write(Char[], Int32, Int32) | 将字符的子数组写入流。第一个Int32;开始写入的 buffer 的索引。第二个Int32:最多读取的字符数。 |
ReadLine() | 从当前流中读取一行字符并将数据作为字符串返回。 |
Dispose() | 释放由 TextWriter对象使用的所有资源。 |
Write(String) | 将字符串写入流 |
WriteLine() | 将行终止符写入文本流。 |
3.1.2 代码示例
static void Main(string[] args)
{
//获取C盘下的子文件目录
DirectoryInfo cDirs = new DirectoryInfo(@"G:\Desktop\archive1");
//* (星号):在该位置的零个或多个字符。?(问号):在该位置的零个或一个字符。
FileInfo[] directoryInfos = cDirs.GetFiles("*",SearchOption.AllDirectories);
// 将目录名写入文件
using (StreamWriter sw = new StreamWriter("G:\\Desktop\\archive1\\Test3.txt"))
{
foreach (FileInfo dir in directoryInfos)
{
sw.WriteLine(dir.FullName);
}
}
// 读取文件的每一行
string line = "";
using (StreamReader sr = new StreamReader("G:\\Desktop\\archive1\\Test3.txt"))
{
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
运行结果
G:\Desktop\archive1\AppSettings.dat
G:\Desktop\archive1\Test3.txt
G:\Desktop\archive1\新建文件夹\MyTest.txt
G:\Desktop\archive1\新建文件夹\MyTest1.txt
其它两对StringReader
与 StringWriter
和TextReader
与 TextWriter
可阅读参考文献:
更多I/O流通用案例:
通用 I/O 任务docs.microsoft.com/zh-cn/dotnet/standard/io/common-i-o-tasksC#系列教程系列将持续更新,和大家一起学习、共同进步!
往期推荐
智能建造小硕:C#中常用I/O流介绍、 FileStream类及FileMode、FileAccess、FileShare1 赞同 · 0 评论文章 智能建造小硕:详细总结C#中的文件和I/O流之文件和目录(File 、 FileInfo、Directory、DirectoryInfo和Path)1 赞同 · 0 评论文章 智能建造小硕:一文读懂C#中的正则表达式知识(字符转义/字符类/ 定位点/ 分组构造 /数量词/反向引用构造/替换构造/替代/正则表达式选项)(理论篇)1 赞同 · 0 评论文章欢迎关注公众号【智能建造小硕】(分享计算机编程、人工智能、智能建造、日常学习和科研经验等,欢迎大家关注交流。)
标签:StreamWriter,字节,字符,C#,写入,WriteLine,StreamReader,读取器,读取 From: https://www.cnblogs.com/sexintercourse/p/16647555.html