C# 输入和输出

来源:这里教程网 时间:2026-02-17 08:44:21 作者:

本章专门介绍 C# 中的输入和输出, C# 中的输入和输出基于流。

C# 流

流是字节序列的抽象,例如文件,输入/输出设备,进程间通信管道或 TCP / IP 套接字。 流将数据从一个点传输到另一点。 流还能够处理数据。 例如,他们可以压缩或加密数据。 在.NET Framework 中,System.IO命名空间包含允许对数据流和文件进行读写的类型。

C# 为File类中的 I / O 操作提供了高级方法,为StreamReader或StreamWriter等类提供了较低级的方法。

处理异常

I / O 操作容易出错。 我们可能会遇到FileNotFoundException或UnauthorizedAccessException之类的异常。 与 Java 不同,C# 不会强制程序员手动处理异常。 由程序员决定是否手动处理异常。 如果在try/catch/finally结构中未手动处理该异常,则该异常由 CLR 处理。

释放资源

I / O 资源必须释放。 可以使用Dispose()方法在 finally 子句中手动释放资源。 using关键字可用于自动释放资源。 同样,File类中的方法为我们释放了资源。

示例文本文件

在示例中,我们使用以下简单文本文件:

thermopylae.txt

The Battle of Thermopylae was fought between an alliance of Greek city-states,led by King Leonidas of Sparta, and the Persian Empire of Xerxes I over thecourse of three days, during the second Persian invasion of Greece.

C# File.ReadAllText

File提供了用于创建,复制,删除,移动和打开单个文件的静态方法,并有助于创建 FileStream 对象。

Note: The File.ReadAllText() is not suited for reading very large files.

File.ReadAllText()打开一个文件,以指定的编码读取文件中的所有文本,然后关闭该文件。

Program.cs

using System;using System.IO;using System.Text;namespace ReadFileIntoString{    class Program    {        static void Main(string[] args)        {            var path = @"C:\Users\Jano\Documents\thermopylae.txt";            var text = File.ReadAllText(path, Encoding.UTF8);            Console.WriteLine(text);        }    }}

该程序读取thermopylae.txt文件的内容,并将其打印到控制台。

var text = File.ReadAllText(path, Encoding.UTF8);

我们一次性将整个文件读成字符串。 在第二个参数中,我们指定编码。

$ dotnet runThe Battle of Thermopylae was fought between an alliance of Greek city-states,led by King Leonidas of Sparta, and the Persian Empire of Xerxes I over thecourse of three days, during the second Persian invasion of Greece.

这是输出。

C# File.ReadAllLines

File.ReadAllLines()打开一个文本文件,将文件的所有行读入字符串数组,然后关闭文件。

File.ReadAllLines()是一种使用 C# 读取文件的便捷方法。 处理非常大的文件时,不应使用它。

Program.cs

using System;using System.IO;namespace ReadAllLines{    class Program    {        static void Main(string[] args)        {            var path = @"C:\Users\Jano\Documents\thermopylae.txt";            string[] lines = File.ReadAllLines(path);            foreach (string line in lines)            {                Console.WriteLine(line);            }        }    }}

该示例将文件中的所有行读入字符串数组。 我们在 foreach 循环中遍历数组,并将每一行打印到控制台。

C# 创建文件

File.CreateText()创建或打开用于写入 UTF-8 编码文本的文件。 如果文件已经存在,则其内容将被覆盖。

Program.cs

using System;using System.IO;namespace CreateFileEx{    class Program    {        static void Main()        {            var path = @"C:\Users\Jano\Documents\cars.txt";            using (StreamWriter sw = File.CreateText(path))            {                sw.WriteLine("Hummer");                sw.WriteLine("Skoda");                sw.WriteLine("BMW");                sw.WriteLine("Volkswagen");                sw.WriteLine("Volvo");            }        }    }}

在示例中,我们创建一个cars.txt文件,并将一些汽车名称写入其中。

using (StreamWriter sw = File.CreateText(path))

CreateText()方法创建或打开一个文件,用于写入 UTF-8 编码的文本。 它返回一个StreamWriter对象。

sw.WriteLine("Hummer");sw.WriteLine("Skoda");...

我们向流写入两行。

$ cat C:\Users\Jano\Documents\cars.txtHummerSkodaBMWVolkswagenVolvo

我们已成功将五个汽车名称写入文件。

C# 创建,最后写入,最后访问时间

使用File类,我们可以获取文件的创建,最后写入和最后访问时间。 Exists()方法确定指定的文件是否存在。

Program.cs

using System;using System.IO;namespace FileTimes{    class Program    {        static void Main(string[] args)        {           var path = @"C:\Users\Jano\Documents\cars.txt";            if (File.Exists(path))            {                Console.WriteLine(File.GetCreationTime(path));                Console.WriteLine(File.GetLastWriteTime(path));                Console.WriteLine(File.GetLastAccessTime(path));            }        }    }}

如果存在指定的文件,我们将确定其创建,最后写入和最后访问时间。

if (File.Exists(path))

如果调用方具有所需的权限并且路径包含现有文件的名称,则Exists()方法返回true。 否则为false。 如果 path 为null,无效路径或长度为零的字符串,则此方法还返回false。

Console.WriteLine(File.GetCreationTime(path));Console.WriteLine(File.GetLastWriteTime(path));Console.WriteLine(File.GetLastAccessTime(path));

我们得到指定文件的创建时间,上次写入时间和上次访问时间。

$ dotnet run10/13/2019 1:59:03 PM10/13/2019 1:59:03 PM10/13/2019 1:59:03 PM

这是一个示例输出。

C# 复制文件

File.Copy()方法将现有文件复制到新文件。 它允许覆盖同名文件。

Program.cs

using System;using System.IO;namespace CopyFileEx{    class Program    {        static void Main(string[] args)        {            var srcPath = @"C:\Users\Jano\Documents\cars.txt";            var destPath = @"C:\Users\Jano\Documents\cars2.txt";            File.Copy(srcPath, destPath, true);            Console.WriteLine("File copied");        }    }}

然后,我们将文件的内容复制到另一个文件。

var srcPath = @"C:\Users\Jano\Documents\cars.txt";var destPath = @"C:\Users\Jano\Documents\cars2.txt";

这是源文件和目标文件。

File.Copy(srcPath, destPath, true);

Copy()方法复制文件。 第三个参数指定是否应覆盖文件(如果存在)。

$ dotnet runFile copied

This is a sample output.

C# IDisposable接口

流实现IDisposable接口。 实现此接口的对象必须尽早手动处理。 这是通过在 finally 块中调用Dispose()方法或利用using语句来完成的。

Program.cs

using System;using System.IO;namespace ManualRelease{    class Program    {        static void Main(string[] args)        {            StreamReader sr = null;            var path = @"C:\Users\Jano\Documents\thermopylae.txt";            try            {                sr = new StreamReader(path);                Console.WriteLine(sr.ReadToEnd());            }            catch (IOException e)            {                Console.WriteLine("Cannot read file");                Console.WriteLine(e.Message);            }            catch (UnauthorizedAccessException e)            {                Console.WriteLine("Cannot access file");                Console.WriteLine(e.Message);            }            finally            {                 sr?.Dispose();            }        }    }}

在此示例中,我们从磁盘上的文件读取字符。 我们手动释放分配的资源。

sr = new StreamReader(path);Console.WriteLine(sr.ReadToEnd());

StreamReader类用于读取字符。 其父级实现IDisposable接口。

} catch (IOException e){    Console.WriteLine("Cannot read file");    Console.WriteLine(e.Message);} catch (UnauthorizedAccessException e){    Console.WriteLine("Cannot access file");    Console.WriteLine(e.Message);}

可能的异常在 catch 块中处理。

finally{    sr?.Dispose();}

在 finally 块中,Dispose()方法清理资源。 使用空条件运算符时,仅当变量不是null时,才调用该方法。

C# 使用语句

using语句定义一个范围,在该范围的末尾将放置一个对象。 它提供了一种方便的语法,可确保正确使用IDisposable对象。

Program.cs

using System;using System.IO;namespace AutomaticCleanup{    class Program    {        static void Main(string[] args)        {            var path = @"C:\Users\Jano\Documents\thermopylae.txt";            using (var sr = new StreamReader(path))            {                Console.WriteLine(sr.ReadToEnd());            }        }    }}

该示例读取thermopylae.txt文件的内容。 资源通过using语句释放。 如果我们不处理 IO 异常,则 CLR 将处理它们。

C# using声明

using声明是在using关键字之后的变量声明。 它告诉编译器声明的变量应放在封闭范围的末尾。 从 C# 8.0 开始,using 声明可用。

Program.cs

using System;using System.IO;namespace UsingDeclaration{    class Program    {        static void Main(string[] args)        {            var path = @"C:\Users\Jano\Documents\thermopylae.txt";            using var sr = new StreamReader(path);            Console.WriteLine(sr.ReadToEnd());        }    }}

该示例读取thermopylae.txt文件的内容。 当sr变量超出范围时(在 Main()方法的末尾),将自动清除资源。

C# MemoryStream

MemoryStream是用于处理计算机内存中数据的流。

Program.cs

using System;using System.IO;namespace MemoryStreamEx{    class Program    {        static void Main(string[] args)        {            using var ms = new MemoryStream(6);            ms.WriteByte(9);            ms.WriteByte(11);            ms.WriteByte(6);            ms.WriteByte(8);            ms.WriteByte(3);            ms.WriteByte(7);            ms.Position = 0;            int rs = ms.ReadByte();            do            {                Console.WriteLine(rs);                rs = ms.ReadByte();            } while (rs != -1);        }    }}

我们用MemoryStream将六个数字写入存储器。 然后,我们读取这些数字并将其打印到控制台。

using var ms = new MemoryStream(6);

该行创建并初始化一个容量为六个字节的MemoryStream对象。

ms.WriteByte(9);ms.WriteByte(11);ms.WriteByte(6);...

WriteByte()方法在当前位置的当前流中写入一个字节。

ms.Position = 0;

我们使用Position属性将光标在流中的位置设置为开头。

do{    Console.WriteLine(rs);    rs = ms.ReadByte();} while (rs != -1);

在这里,我们从流中读取所有字节并将其打印到控制台。

$ dotnet run9116837

这是示例的输出。

C# StreamReader

StreamReader从字节流中读取字符。 默认为 UTF-8 编码。

Program.cs

using System;using System.IO;namespace ReadFileEx{    class Program    {        static void Main(string[] args)        {            var path = @"C:\Users\Jano\Documents\thermopylae.txt";            using var sr = new StreamReader(path);            while (sr.Peek() >= 0)            {                Console.WriteLine(sr.ReadLine());            }        }    }}

我们读取文件的内容。 这次我们使用ReadLine()方法逐行读取文件。

while (sr.Peek() >= 0){    Console.WriteLine(sr.ReadLine());}

Peek()方法返回下一个可用字符,但不使用它。 它指示我们是否可以再次调用ReadLine()方法。 如果没有要读取的字符,则返回-1。

C# 计数行

在下一个示例中,我们将对行进行计数。

Program.cs

using System;using System.IO;namespace CountingLines{    class Program    {        static void Main(string[] args)        {            int count = 0;            var path = @"C:\Users\Jano\Documents\thermopylae.txt";            using var sr = new StreamReader(path);            while (sr.ReadLine() != null)            {                count++;            }            Console.WriteLine("There are {0} lines", count);        }    }}

我们正在计算文件中的行数。

while(stream.ReadLine() != null){    count++;}

在 while 循环中,我们使用ReadLine()方法从流中读取一行。 如果到达输入流的末尾,它将从流或null中返回一行。

$ dotnet runThere are 3 lines

该文件有三行。

C# StreamWriter

StreamWriter以特定编码将字符写入流。

Program.cs

using System;using System.IO;namespace WriteToFile{    class Program    {        static void Main(string[] args)        {            var path = @"C:\Users\Jano\Documents\newfile.txt";            using var sw = new StreamWriter(path);            sw.WriteLine("Today is a beautiful day.");        }    }}

该示例使用StreamWriter将字符串写入文件。

using (var sw = new StreamWriter(path))

我们创建一个新的StreamWriter。 默认值是 UTF-8。 StreamWriter将路径作为参数。 如果文件存在,它将被覆盖; 否则,将创建一个新文件。

$ dotnet run$ cat C:\Users\Jano\Documents\newfile.txtToday is a beautiful day.

我们已经使用cat命令显示了文件的内容。

C# FileStream

FileStream为文件提供流,同时支持同步和异步读取和写入操作。

StreamReader和StreamWriter处理文本数据,而FileStream处理字节。

Program.cs

using System.IO;using System.Text;namespace FileStreamEx{    class Program    {        static void Main(string[] args)        {            var path = @"C:\Users\Jano\Documents\newfile2.txt";            using var fs = new FileStream(path, FileMode.Append);            var text = "Фёдор Михайлович Достоевский\n";            byte[] bytes = new UTF8Encoding().GetBytes(text);            fs.Write(bytes, 0, bytes.Length);        }    }}

我们用俄语西里尔字母写一些文本到文件中。

using System.Text;

UTF8Encoding类位于System.Text命名空间中。

using var fs = new FileStream(path, FileMode.Append);

创建一个FileStream对象。 第二个参数是打开文件的模式。 附加模式将打开文件(如果存在)并查找到文件末尾,或创建一个新文件。

var text = "Фёдор Михайлович Достоевский";

这是俄文西里尔文的文字。

byte[] bytes = new UTF8Encoding().GetBytes(text);

从俄语西里尔字母文本创建一个字节数组。

fs.Write(bytes, 0, bytes.Length);

我们将字节写入文件流。

$ cat C:\Users\Jano\Documents\newfile2.txtФёдор Михайлович Достоевский

我们显示创建文件的内容。

C# XmlTextReader

我们可以使用流来读取 XML 数据。 XmlTextReader是用于读取 C# 中的 XML 文件的类。 该类是仅转发和只读的。

我们有以下 XML 测试文件:

languages.xml

<?xml version="1.0" encoding="utf-8" ?><languages>    <language>Python</language>    <language>Ruby</language>    <language>Javascript</language>    <language>C#</language></languages>

此文件包含自定义 XML 标记之间的语言名称。

Program.cs

using System;using System.IO;using System.Xml;namespace ReadingXMLFile{    public class Program    {        static void Main()        {            string path = @"C:\Users\Jano\Documents\languages.xml";            using (var xreader = new XmlTextReader(path))            {                xreader.MoveToContent();                while (xreader.Read())                {                    var node = xreader.NodeType switch                    {                        XmlNodeType.Element => String.Format("{0}: ", xreader.Name),                        XmlNodeType.Text => String.Format("{0} \n", xreader.Value),                        _ => ""                    };                    Console.Write(node);                }            }        }    }}

本示例从 XML 文件读取数据并将其打印到终端。

using System.Xml;

System.Xml命名空间包含与 Xml 读写相关的类。

using (var xreader = new XmlTextReader(path))

创建一个XmlTextReader对象。 它是一种读取器,可提供对 XML 数据的快速,非缓存且仅前向访问。 它以文件名作为参数。

xreader.MoveToContent();

MoveToContent()方法移至 XML 文件的实际内容。

while (xreader.Read())

该行从流中读取下一个节点。 如果没有更多节点,则Read()方法返回false。

var node = xreader.NodeType switch{    XmlNodeType.Element => String.Format("{0}: ", xreader.Name),    XmlNodeType.Text => String.Format("{0} \n", xreader.Value),    _ => ""};Console.Write(node);

在这里,我们打印元素名称和元素文本。

$ dotnet runlanguage: Pythonlanguage: Rubylanguage: Javascriptlanguage: C#

这是示例的输出。

C# 创建,移动目录

System.IO.Directory是一个类,具有用于在目录和子目录中创建,移动和枚举的静态方法。

Program.cs

using System;using System.IO;namespace DirectoryEx{    class Program    {        static void Main(string[] args)        {            Directory.CreateDirectory("temp");            Directory.CreateDirectory("newdir");            Directory.Move("temp", "temporary");        }    }}

我们创建两个目录,然后重命名其中一个目录。 目录在项目文件夹中创建。

Directory.CreateDirectory("temp");

CreateDirectory()方法创建一个新目录。

Directory.Move("temp", "temporary");

Move()方法为指定的目录提供一个新名称。

C# DirectoryInfo

DirectoryInfo公开了用于在目录和子目录中创建,移动和枚举的实例方法。

Program.cs

using System;using System.IO;namespace ShowContents{    class Program    {        static void Main(string[] args)        {            var path = @"C:\Users\Jano\Documents";            var dirInfo = new DirectoryInfo(path);            string[] files = Directory.GetFiles(path);            DirectoryInfo[] dirs = dirInfo.GetDirectories();            foreach (DirectoryInfo subDir in dirs)            {                Console.WriteLine(subDir.Name);            }            foreach (string fileName in files)            {                Console.WriteLine(fileName);            }        }    }}

我们使用DirectoryInfo类遍历特定目录并打印其内容。

var path = @"C:\Users\Jano\Documents";var DirInfo = new DirectoryInfo(path);

我们显示指定目录的内容。

string[] files = Directory.GetFiles(path);;

我们使用静态GetFiles()方法获取目录的所有文件。

DirectoryInfo[] dirs = dir.GetDirectories();

我们得到所有目录。

foreach (DirectoryInfo subDir in dirs){    Console.WriteLine(subDir.Name);}

在这里,我们遍历目录并将其名称打印到控制台。

foreach (string fileName in files){    Console.WriteLine(fileName);}

在这里,我们遍历文件数组并将其名称打印到控制台。

相关推荐