文件和流(I/O)

时间:2021-04-01 10:00:47

1.System.IO命名空间

System.IO命名空间主要包括了基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库。

2.Directory(Info)和File(Info)

文件和流(I/O)

FileInfo和DirectoryInfo是获取文件类型或目录细节更好的方式,因为它们的成员往往会返回强类型的对象。
FileSystemInfo属性及抽象方法:

属性/抽象方法 作用
Attribute 获取或设置当前文件关联的特性,由FileAttributes枚举表示
CreateTime 获取或设置当前文件或目录的创建时间
Exists 判断指定文件或目录是否存在
Fullname 获取目录或文件的完整路径
LastAccessTime 获取或设置上次访问当前文件或目录的时间
LastWriteTime 获取或设置上次写入当前文件或目录的时间
Name 获取当前文件或目录的名称
Delete() 删除指定文件或目录
Refresh() 确保当前文件或目录统计信息为最新

3.使用DirectoryInfo类型

DirectoryInfo类型的主要成员:

成员 作用
Create()h和CreateSubdirectory() 按照路径名建立一个目录或一组子目录
Delete() 删除一个目录和它的所有内容
GetDirectories() 返回一个表示当前目录中所有子目录的DirectoryInfo对象数组
GetFile() 返回FileInfo对象数组,表示指定目录下的一组文件
MoveTo() 将一个目录及其内容移动到新路径
Parent 获取指定目录的父目录
Root 获取路径的根部分
文件和流(I/O)文件和流(I/O)
DirectoryInfo dir1 = new DirectoryInfo("."); //当前应用程序目录
DirectoryInfo dir2 = new DirectoryInfo(@"C:\Windows"); // 使用逐字字符串
DirectoryInfo dir3 = new DirectoryInfo(@"C:\New"); 
dir3.Create(); //创建新目录
using System;
using System.IO;
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("***** Fun with Directory(Info) *****\n");
        ShowWindowsDirectoryInfo();
        ;
        Console.ReadLine();
    }
    static void ShowWindowsDirectoryInfo()
    {
        // Dump directory information.
        DirectoryInfo dir = new DirectoryInfo(@"C:\Windows");
        Console.WriteLine("***** Directory Info *****");
        Console.WriteLine("FullName: {0}", dir.FullName);
        Console.WriteLine("Name: {0}", dir.Name);
        Console.WriteLine("Parent: {0}", dir.Parent);
        Console.WriteLine("Creation: {0}", dir.CreationTime);
        Console.WriteLine("Attributes: {0}", dir.Attributes);
        Console.WriteLine("Root: {0}", dir.Root);
        Console.WriteLine("**************************\n");
    }
}
View Code

输出结果如下:

文件和流(I/O)文件和流(I/O)
***** Fun with Directory(Info) *****

***** Directory Info *****
FullName: C:\Windows
Name: Windows
Parent:
Creation: 4/12/2018 5:04:33 AM
Attributes: Directory
Root: C:\
**************************
View Code

3.1 使用DirectoryInfo类型枚举出文件

文件和流(I/O)文件和流(I/O)
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("***** Fun with Directory(Info) *****\n");
        DisplayImageFiles();
        ;
        Console.ReadLine();
    }
    static void DisplayImageFiles()
    {
        DirectoryInfo dir = new DirectoryInfo(@"C:\Windows\Web\Wallpaper");
        // GetFiles()方法返回FileInfo类型的数组
        FileInfo[] imageFiles = dir.GetFiles("*.jpg", SearchOption.AllDirectories);
        Console.WriteLine("Found {0} *.jpg files\n", imageFiles.Length);
        foreach (FileInfo f in imageFiles)
        {
            Console.WriteLine("***************************");
            Console.WriteLine("File name: {0}", f.Name);
            Console.WriteLine("File size: {0}", f.Length);
            Console.WriteLine("Creation: {0}", f.CreationTime);
            Console.WriteLine("Attributes: {0}", f.Attributes);
            Console.WriteLine("***************************\n");
        }
    }
}
View Code

3.2 使用DirectoryInfo类型创建子目录

文件和流(I/O)文件和流(I/O)
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("***** Fun with Directory(Info) *****\n");
        ModifyAppDirectory();
        Console.ReadLine();
    }
    static void ModifyAppDirectory()
    {
        DirectoryInfo dir = new DirectoryInfo(".");
        // 在初始目录下创建\MyFolder
        dir.CreateSubdirectory("MyFolder");
        // 捕获返回的DirectoryInfo类型
        DirectoryInfo myDataFolder = dir.CreateSubdirectory(@"MyFolder2\Data");
        // 输出路径
        Console.WriteLine("New Folder is: {0}", myDataFolder);
    }
}
View Code

输出结果如下:

文件和流(I/O)文件和流(I/O)
***** Fun with Directory(Info) *****

New Folder is: C:\Users\kylew\Desktop\ConsoleApp1\ConsoleApp1\bin\Debug\MyFolder2\Data
View Code

4.使用Directory类型

Directory成员返回的是字符串数据而不是强类型的DirectoryInfo对象

文件和流(I/O)文件和流(I/O)
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("***** Fun with Directory(Info) *****\n");
        FunWithDirectoryType();
        Console.ReadLine();
    }
    static void FunWithDirectoryType()
    {
        // 列出当前所有驱动器
        string[] drives = Directory.GetLogicalDrives();
        Console.WriteLine("Here are your drives:");
        foreach (string s in drives)
            Console.WriteLine("--> {0} ", s);
        // 删除之前建立的目录
        Console.WriteLine("Press Enter to delete directories");
        Console.ReadLine();
        try
        {
            Directory.Delete(@"C:\MyFolder");
            // 第二个参数指定是否删除子目录
            Directory.Delete(@"C:\MyFolder2", true);
        }
        catch (IOException e)
        {
            Console.WriteLine(e.Message);
        }
    }
}
View Code

输出结果如下:

文件和流(I/O)文件和流(I/O)
***** Fun with Directory(Info) *****

Here are your drives:
--> C:\
--> D:\
--> E:\
Press Enter to delete directorie
View Code

5.使用DriveInfo类

文件和流(I/O)文件和流(I/O)
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("***** Fun with DriveInfo *****\n");
        // 获取所有驱动器信息
        DriveInfo[] myDrives = DriveInfo.GetDrives();
        foreach (DriveInfo d in myDrives)
        {
            Console.WriteLine("Name: {0}", d.Name);
            Console.WriteLine("Type: {0}", d.DriveType);
            // 检查驱动器是否准备好
            if (d.IsReady)
            {
                Console.WriteLine("Free space: {0}", d.TotalFreeSpace);
                Console.WriteLine("Format: {0}", d.DriveFormat);
                Console.WriteLine("Label: {0}", d.VolumeLabel);
            }
            Console.WriteLine();
        }
        Console.ReadLine();
    }
}
View Code

输出结果如下:

文件和流(I/O)文件和流(I/O)
***** Fun with DriveInfo *****

Name: C:\
Type: Fixed
Free space: 225707257856
Format: NTFS
Label: OSDisk

Name: D:\
Type: Fixed
Free space: 236758802432
Format: NTFS
Label: Data

Name: E:\
Type: CDRom
View Code

6.使用FileInfo类

FileInfo核心成员:

成员 作用
AppendText() 创建一个StreamWriter类型,用来向文件追加文本
CopyTo() 将现有文件复制到新文件
Create() 创建一个新文件并返回一个FileStream,通过它与新文件进行交互
CreateText() 创建一个写入新文本文件的StramWriter对象
Delete() 删除FileInfo实例绑定的对象
Directory 获取父目录的实例
DirectoryName 获取父母录的完整路径
Length 获取当前文件的大小
MoveTo() 将指定文件移到新位置,并提供指定新文件名的选项
Name 获取文件名
Open() 用各种读/写访问权限和共享权限打开文件
OpenRead() 创建只读FileDtream对象
OpenText() 创建从现有文本文件中读取数据的StreamReader
OpenWrite() 创建只写FileStream类型

6.1 FileInfo.Create()方法

使用FileInfo.Create()方法建立文件句柄

文件和流(I/O)文件和流(I/O)
static voia Main()
{
    FileInfo f = new FileInfo(@"C:\Test.dat"); // 新建文件
    FileStream fs = f.Create(); // 返回的FileStream对象给所有用户授予完全读写权限
    
    // 使用FileStream对象
    
    fs.Close();// 非托管资源,关闭文件流
}
static void Main()
{
    FileInfo f = new FileInfo(@"C:\Test.dat");
    using (FileStream fs = f.Create()) // 为I/O类型定义using域
    {
        // 使用FileStream对象
    }
}
View Code

6.2 FileInfo.Open()方法

使用FileInfo.Open()方法打开现有文件,同时也能用来创建新文件。

文件和流(I/O)文件和流(I/O)
static void Main()
{
    FileInfo f2 = new FileInfo(@"C:\Test2.dat");
    using (FileStream fs2 = f2.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Nonoe))
    {
        //使用FileStream对象
    }
}
View Code

重载的Open()方法需要三个参数,第一个参数指定I/O请求的基本方式(比如新建文件、打开现有文件和追加文件),它的值有FileMode枚举指定:

文件和流(I/O)文件和流(I/O)
public enum FileMode
{
    CreateNew, // 新建文件,若存在则抛出异常
    Create, // 新建文件,若存在则覆盖
    Open, // 打开既有文件,若不存在则抛出异常
    OpenOrCreate, // 若文件存在则打开,否则新建文件
    Truncate, // 打开文件并截断文件为0字节大小
    Append // 打开文件,移动到文件尾部,开始写操作,若不存在则新建文件
}
View Code

第二个参数的值由FileAccess枚举定义,用来决定基层流的读写行为:

文件和流(I/O)文件和流(I/O)
public enum FileAccess
{
    Read,
    Write,
    ReadWrite
}
View Code

第三个参数FileShare指定文件在其他文件处理程序中的共享方式:

文件和流(I/O)文件和流(I/O)
public enum FileShare
{
    Delete,
    Inheritable,
    None,
    Read,
    ReadWrite,
    Write
}
View Code

6.3 FileInfo.OpenRead()和FileInfo.OpenWrite()方法

文件和流(I/O)文件和流(I/O)
static void Main()
{
    // 得到一个只读的FileStream对象
    FileInfo f3 = new FileInfo(@"C:\Test3.dat");
    using (FileStream readOnlyStream = f3.OpenRead())
    {
        // 使用FileStream对象
    }
    // 得到一个只写的FileStream对象
    FileInfo f4 = new FileInfo(@"C:\Test4.dat");
    using (FileStream writeOnlyStream = f4.OpenRead())
    {
        // 使用FileStream对象
    }
}
View Code

6.4 FileInfo.OpenText()方法

FileInfo.OpenText()方法返回的是一个StreamReader类型(而非FileStream类型)的实例。

文件和流(I/O)文件和流(I/O)
static void Main()
{
    FileInfo f5 = new FileInfo(@"C:\boot.ini");
    using (StreamReader sreader = f5.OpenText())
    {
        // 使用StreamReader对象
    }
}
View Code

StreamReader类型提供了从基层文件读取字符数据的方法。

6.5 FileInfo.CreateText()方法和FileInfo.AppendText()方法

CreateText()方法和AppendText()方法都返回一个StreamWriter对象

文件和流(I/O)文件和流(I/O)
static void Main()
{
    FileInfo f6 = new FileInfo(@"C:\Test6.txt");
    using (StreamWriter swriter = f6.CreateText())
    {
        // 使用StreanWriter对象
    }
    FileInfo f7 = new FileInfo(@"C:\Test6.txt");
    using (StreamWriter swriterAppend = f6.AppendText())
    {
        // 使用StreanWriter对象
    }
    
}
View Code

StreamWriter类型提供了从基层文件写入字符数据的方法。

7.使用File类

File类型的静态成员提供了与FileInfo类型差不多的功能,前面的每一个FileStream示例都可以用File类型来简化

文件和流(I/O)文件和流(I/O)
static void Main()
{
    using (FileStream fs = File.Create(@"C:\Test.dat"))
    {}
    using (FileStream fs2 = File.Open(@"C:\Test2.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Nonoe))
    {}
    using (FileStream readOnlyStream = File.OpenRead(@"C:\Test3.dat"))
    {}
    using (FileStream writeOnlyStream = File.OpenRead(@"C:\Test4.dat"))
    {}
    using (StreamReader sreader = File.OpenText(@"C:\boot.ini"))
    {}
    using (StreamWriter swriter = File.CreateText(@"C:\Test6.txt"))
    {}
    using (StreamWriter swriterAppend = File.AppendText(@"C:\Test6.txt"))
    {}
}
View Code

File类型提供了一些独有的成员,可以极大地简化读写文本数据的过程:

方法 作用
ReadAllBytes() 打开指定文件,以字节数组形式返回二进制数据,然后关闭文件
ReadAllLines() 打开指定文件,以字符串数组形式返回字符数据,然后关闭文件
ReadAllText() 打开指定文件,以System.String形式返回字符数据,然后关闭文件
WriteAllBytes() 打开指定文件,写入字节数组,然后关闭文件
WriteAllLines() 打开指定文件,写入字符串数组,然后关闭文件
WriteAllText() 打开指定文件,写入字符数据,然后关闭文件
文件和流(I/O)文件和流(I/O)
class Program
{
    static void Main()
    {
        Console.WriteLine("*** Simple I/O with the File type ***");
        string[] myTasks = {
            "Fix bathroom sink", "Call Dave",
            "Call Mom and Dad", "Play Xbox 360"
        };
        File.WriteAllLines(@"C:\tasks.txt", myTasks);
        foreach (string task in File.ReadAllLines(@"C:\tasks.txt"))
        {
            Console.WriteLine("TODO: {0}", task);
        }
        Console.ReadKey();
    }
}
View Code

输出结果如下:

文件和流(I/O)文件和流(I/O)
*** Simple I/O with the File type ***
TODO: Fix bathroom sink
TODO: Call Dave
TODO: Call Mom and Dad
TODO: Play Xbox 360
View Code

8.Stream抽象类

抽象Stream成员:

成员 作用
CanRead、CanWrite、CanSeek 检测当前流是否支持读、写的寻址
Close() 关闭当前流并释放与之关联的所有资源
Flush() 使用当前的缓冲状态更新基层的数据源或存储库
Lenght 返回流的长度,以字节表示
Position 检测在当前流中的位置
Read()和ReadByte() 从当前流读取字节序列(或一个字节),并将此流中的位置偏移读取的字节数
Seek() 设置当前流中的位置
SetLength() 设置当前六的长度
Write()和WriteByte() 向当前流中写入字节序列(或一个字节),并将此流中的当前位置偏移写入的字节数

使用FileStream
因为FileStream只能处理原始字节,所以必须把System.String编码成相应的字节数组,使用System.Text下的Encoding类型实现字符串与字节数组间的编码/解码。

文件和流(I/O)文件和流(I/O)
using System;
using System.IO;
using System.Text;

namespace FileStreamApp
{
    class Program
    {
        // Don't forget to import the System.Text and System.IO namespaces.
        static void Main(string[] args)
        {
            Console.WriteLine("***** Fun with FileStreams *****\n");
            try
            {
                // 获取一个FileStream对象
                using (FileStream fStream = File.Open(@"D:\myMessage.dat",
                  FileMode.Create))
                {
                    // 把字符串编码成字节数组
                    string msg = "Hello!";
                    byte[] msgAsByteArray = Encoding.Default.GetBytes(msg);
                    // 将byte[]写入文件
                    fStream.Write(msgAsByteArray, 0, msgAsByteArray.Length);
                    // 重置流内部位置
                    fStream.Position = 0;
                    // Read the types from file and display to console.
                    Console.Write("Your message as an array of bytes: ");
                    byte[] bytesFromFile = new byte[msgAsByteArray.Length];
                    for (int i = 0; i < msgAsByteArray.Length; i++)
                    {
                        bytesFromFile[i] = (byte)fStream.ReadByte();
                        Console.Write(bytesFromFile[i]);
                    }
                    // 显示解码后字符串
                    Console.Write("\nDecoded Message: ");
                    Console.WriteLine(Encoding.Default.GetString(bytesFromFile));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadLine();
        }
    }
}
View Code

输出结果如下:

文件和流(I/O)文件和流(I/O)
***** Fun with FileStreams *****

Your message as an array of bytes: 7210110810811133
Decoded Message: Hello!
View Code

9.使用StreamWriter和StreamReader类型

StreamWriter和StreamReader类默认使用Unicode字符。StreamWriter类型从TextWriter抽象基类派生。 TextWriter核心成员:

成员 作用
Close() 关闭当前编写器并释放任何与之关联的系统资源
Flush() 清理当前编写器的所有缓冲区,使所有缓冲数据写入基础设备,但不关闭编写器
NewLine 代表派生的编写器类的行结束符字符串(\r\n)
Write() 此重载方法将一行写入文本流,不跟行结束符
WriteLine() 此重载方法将一行写入流,后跟行结束符

9.1 写文本文件

文件和流(I/O)文件和流(I/O)
using System;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("***** Fun with StreamWriter / StreamReader *****\n");
        // Get a StreamWriter and write string data.
        using (StreamWriter writer = File.CreateText("reminders.txt"))
        {
            writer.WriteLine("Don't forget Mother's Day this year...");
            writer.WriteLine("Don't forget Father's Day this year...");
            writer.WriteLine("Don't forget these numbers:");
            for (int i = 0; i < 10; i++)
                writer.Write(i + " ");
            // Insert a new line.
            writer.Write(writer.NewLine);
        }
        Console.WriteLine("Created file and wrote some thoughts...");
        Console.ReadLine();
    }
}
View Code

9.2 读文本文件

TextReader主要成员:

成员 作用
Peek() 返回下一个可用字符,而不更改读取器位置,返回-1表示已经到了流的尾部
Read() 从输出流中读取数据
ReadBlock() 从当前流中读取最大计数字符,并从索引开始将数据写入缓冲区
ReadLine() 从当前流中读取一行字符,并将数据作为字符串返回(返回空字符串代表EOF)
ReadToEnd() 读取从当前位置到流结尾的所有字符,并将它们作为一个字符串返回
文件和流(I/O)文件和流(I/O)
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("***** Fun with StreamWriter / StreamReader *****\n");
        Console.WriteLine("Here are your thoughts:\n");
        using (StreamReader sr = File.OpenText("reminders.txt"))
        {
            string input = null;
            while ((input = sr.ReadLine()) != null)
            {
                Console.WriteLine(input);
            }
        }
        Console.ReadLine();
    }
}
View Code

输出结果入下:

文件和流(I/O)文件和流(I/O)
***** Fun with StreamWriter / StreamReader *****

Here are your thoughts:

Don't forget Mother's Day this year...
Don't forget Father's Day this year...
Don't forget these numbers:
0 1 2 3 4 5 6 7 8 9
View Code

9.3 直接创建StreamWriter/StreamReader类型

可以通过直接创建StreamWriter/StreamReader类型来使用StreamWriter/StreamReader。

文件和流(I/O)文件和流(I/O)
static void Main()
{
    // 得到一个StreamWriter,然后写入字符串数据
    using (StreamWriter writer = new StreamWriter("reminders.txt")){}
    // 从文件读取数据
    using (StreamReader sr = new StreamReader("reminders.txt")){}
}
View Code

10.使用StringWriter和StringReader类型

使用StringWriter和StringReader类型,可以将文本信息当作内存中的字符一样来处理。

文件和流(I/O)文件和流(I/O)
using System;
using System.IO;
using System.Text;
namespace StringReaderWriterApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("***** Fun with StringWriter / StringReader *****\n");
            // Create a StringWriter and emit character data to memory.
            using (StringWriter strWriter = new StringWriter())
            {
                strWriter.WriteLine("Don't forget Mother's Day this year...");
                Console.WriteLine("Contents of StringWriter:\n{0}", strWriter);
                // Get the internal StringBuilder.
                StringBuilder sb = strWriter.GetStringBuilder();
                sb.Insert(0, "Hey!! ");
                Console.WriteLine("-> {0}", sb.ToString());
                sb.Remove(0, "Hey!! ".Length);
                Console.WriteLine("-> {0}", sb.ToString());
            }
            using (StringWriter strWriter = new StringWriter())
            {
                strWriter.WriteLine("Don't forget Mother's Day this year...");
                Console.WriteLine("Contents of StringWriter:\n{0}", strWriter);
                // Read data from the StringWriter.
                using (StringReader strReader = new StringReader(strWriter.ToString()))
                {
                    string input = null;
                    while ((input = strReader.ReadLine()) != null)
                    {
                        Console.WriteLine(input);
                    }
                }
            }
            Console.ReadLine();
        }
    }
}
View Code

输出结果如下:

文件和流(I/O)文件和流(I/O)
***** Fun with StringWriter / StringReader *****

Contents of StringWriter:
Don't forget Mother's Day this year...

-> Hey!! Don't forget Mother's Day this year...

-> Don't forget Mother's Day this year...

Contents of StringWriter:
Don't forget Mother's Day this year...

Don't forget Mother's Day this year...
View Code

11.使用BinaryWriter和BinaryReader

使用BinaryWriter和BinaryReader可以从基层流中以简介的二进制格式读取或写入离散数据类型,可以读取数据,而非字符串。 BinaryWriter核心成员:

成员 作用
BaseStream 此只读属性提供了BinaryWriter对象使用的基层流的访问
Close() 关闭二进制流
Flush() 刷新二进制流
Seek() 设置当前流位置
Write() 将值写入当前流

BinaryReader核心成员:

成员 作用
BaseStream 此只读属性提供了BinaryWriter对象使用的基层流的访问
Close() 关闭二进制阅读器
PeekChar() 返回下一个可用的字符,且不改变指针位置
Read() 读取给定的字节或字符,并把它们存入数组
ReadXXXX() 定义了许多Read()方法来从流中获取下一个类型(ReadBoolean()、ReadByte()和ReadInt32())
文件和流(I/O)文件和流(I/O)
using System;
using System.IO;
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("***** Fun with Binary Writers / Readers *****\n");
        // 为文件打开一个二进制编写器
        FileInfo f = new FileInfo("BinFile.dat");
        using (BinaryWriter bw = new BinaryWriter(f.OpenWrite()))
        {
            // 输出BaseStream类型,此处为System.IO.FileStream
            Console.WriteLine("Base stream is: {0}", bw.BaseStream);
            double aDouble = 1234.67;
            int anInt = 34567;
            string aString = "A, B, C";
            // 写入数据
            bw.Write(aDouble);
            bw.Write(anInt);
            bw.Write(aString);
        }
        Console.WriteLine("Done!");
        // 从流中读取二进制数据
        using (BinaryReader br = new BinaryReader(f.OpenRead()))
        {
            Console.WriteLine(br.ReadDouble());
            Console.WriteLine(br.ReadInt32());
            Console.WriteLine(br.ReadString());
        }
        Console.ReadLine();
    }
}
View Code

输出结果如下:

文件和流(I/O)文件和流(I/O)
***** Fun with Binary Writers / Readers *****

Base stream is: System.IO.FileStream
Done!
1234.67
34567
A, B, C
View Code