**前言:**文件操作及相关的流操作是每一种编程语言的必备部分
就我学过的Java来对比最近正在学习的C#,对比发现,确实
C#文件操作相关相比Java较为简单,比较好使用
第一,C#将File和Dirtory明确的分开,避免混淆了文件夹和具体文件。
第二,C#的文件操作分一套工厂类和一套普通的使用类。
整个分割线吧------------------------------------------------------------------------------------------------------------------
工厂类
这点可以从源码分析看出,File和Dirtory都是一组静态类,
其中的所有方法都是静态方法,也就是说,它不可以生成实体对象。
public static class File
{
public static void AppendAllLines(string path, IEnumerable<string> contents);
public static void AppendAllLines(string path, IEnumerable<string> contents, Encoding encoding);
public static Task AppendAllLinesAsync(string path, IEnumerable<string> contents, CancellationToken cancellationToken = default);
public static void AppendAllText(string path, string contents);
public static void AppendAllText(string path, string contents, Encoding encoding);
public static StreamWriter AppendText(string path);
public static void Copy(string sourceFileName, string destFileName);
public static void Copy(string sourceFileName, string destFileName, bool overwrite);
public static FileStream Create(string path);
public static FileStream Create(string path, int bufferSize);
public static FileStream Create(string path, int bufferSize, FileOptions options);
public static StreamWriter CreateText(string path);
public static void Decrypt(string path);
public static void Delete(string path);
public static void Encrypt(string path);
public static bool Exists(string path);
public static DateTime GetCreationTime(string path);
public static DateTime GetCreationTimeUtc(string path);
public static DateTime GetLastAccessTime(string path);
public static DateTime GetLastAccessTimeUtc(string path);
public static DateTime GetLastWriteTime(string path);
public static DateTime GetLastWriteTimeUtc(string path);
public static void Move(string sourceFileName, string destFileName);
public static FileStream Open(string path, FileMode mode);
public static FileStream Open(string path, FileMode mode, FileAccess access);
public static FileStream Open(string path, FileMode mode, FileAccess access, FileShare share);
public static FileStream OpenRead(string path);
public static StreamReader OpenText(string path);
public static FileStream OpenWrite(string path);
public static byte[] ReadAllBytes(string path);
public static Task<byte[]> ReadAllBytesAsync(string path, CancellationToken cancellationToken = default);
public static string[] ReadAllLines(string path);
public static string[] ReadAllLines(string path, Encoding encoding);
public static Task<string[]> ReadAllLinesAsync(string path, CancellationToken cancellationToken = default);
public static string ReadAllText(string path);
public static string ReadAllText(string path, Encoding encoding);
public static Task<string> ReadAllTextAsync(string path, CancellationToken cancellationToken = default);
public static Task<string> ReadAllTextAsync(string path, Encoding encoding, CancellationToken cancellationToken = default);
public static IEnumerable<string> ReadLines(string path);
public static IEnumerable<string> ReadLines(string path, Encoding encoding);
public static void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName);
public static void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors);
public static void SetAttributes(string path, FileAttributes fileAttributes);
public static void SetCreationTimeUtc(string path, DateTime creationTimeUtc);
public static void SetLastAccessTime(string path, DateTime lastAccessTime);
public static void SetLastAccessTimeUtc(string path, DateTime lastAccessTimeUtc);
public static void SetLastWriteTime(string path, DateTime lastWriteTime);
public static void SetLastWriteTimeUtc(string path, DateTime lastWriteTimeUtc);
public static void WriteAllBytes(string path, byte[] bytes);
public static Task WriteAllBytesAsync(string path, byte[] bytes, CancellationToken cancellationToken = default);
public static void WriteAllLines(string path, string[] contents);
public static void WriteAllLines(string path, IEnumerable<string> contents);
public static void WriteAllLines(string path, string[] contents, Encoding encoding);
public static void WriteAllLines(string path, IEnumerable<string> contents, Encoding encoding);
public static Task WriteAllLinesAsync(string path, IEnumerable<string> contents, CancellationToken cancellationToken = default);
public static void WriteAllText(string path, string contents);
public static void WriteAllText(string path, string contents, Encoding encoding);
public static Task WriteAllTextAsync(string path, string contents, CancellationToken cancellationToken = default);
public static Task WriteAllTextAsync(string path, string contents, Encoding encoding, CancellationToken cancellationToken = default);
}
}
public static class Directory
{
public static DirectoryInfo CreateDirectory(string path);
public static void Delete(string path);
public static void Delete(string path, bool recursive);
public static IEnumerable<string> EnumerateDirectories(string path);
public static IEnumerable<string> EnumerateDirectories(string path, string searchPattern);
public static IEnumerable<string> EnumerateDirectories(string path, string searchPattern, EnumerationOptions enumerationOptions);
public static IEnumerable<string> EnumerateDirectories(string path, string searchPattern, SearchOption searchOption);
public static IEnumerable<string> EnumerateFiles(string path, string searchPattern, SearchOption searchOption);
public static IEnumerable<string> EnumerateFiles(string path, string searchPattern, EnumerationOptions enumerationOptions);
public static IEnumerable<string> EnumerateFiles(string path);
public static IEnumerable<string> EnumerateFileSystemEntries(string path);
public static IEnumerable<string> EnumerateFileSystemEntries(string path, string searchPattern);
public static IEnumerable<string> EnumerateFileSystemEntries(string path, string searchPattern, EnumerationOptions enumerationOptions);
public static IEnumerable<string> EnumerateFileSystemEntries(string path, string searchPattern, SearchOption searchOption);
public static bool Exists(string path);
public static DateTime GetCreationTime(string path);
public static DateTime GetCreationTimeUtc(string path);
public static string[] GetDirectories(string path, string searchPattern, EnumerationOptions enumerationOptions);
public static string[] GetDirectories(string path, string searchPattern, SearchOption searchOption);
public static string[] GetDirectories(string path);
public static string[] GetDirectories(string path, string searchPattern);
public static string GetDirectoryRoot(string path);
public static string[] GetFiles(string path);
public static string[] GetFiles(string path, string searchPattern);
public static string[] GetFiles(string path, string searchPattern, EnumerationOptions enumerationOptions);
public static string[] GetFiles(string path, string searchPattern, SearchOption searchOption);
public static string[] GetFileSystemEntries(string path);
public static string[] GetFileSystemEntries(string path, string searchPattern);
public static string[] GetFileSystemEntries(string path, string searchPattern, EnumerationOptions enumerationOptions);
public static string[] GetFileSystemEntries(string path, string searchPattern, SearchOption searchOption);
public static DateTime GetLastAccessTime(string path);
public static DateTime GetLastAccessTimeUtc(string path);
public static DateTime GetLastWriteTime(string path);
public static DateTime GetLastWriteTimeUtc(string path);
public static string[] GetLogicalDrives();
public static void Move(string sourceDirName, string destDirName);
public static void SetCreationTime(string path, DateTime creationTime);
public static void SetCurrentDirectory(string path);
public static void SetLastAccessTime(string path, DateTime lastAccessTime);
public static void SetLastAccessTimeUtc(string path, DateTime lastAccessTimeUtc);
public static void SetLastWriteTimeUtc(string path, DateTime lastWriteTimeUtc);
}
}
可以看出,非常简洁,全部都是静态方法,也可以说是工厂方法,可以直接调用,非常的简单
下面来简单的使用一下
static void Main(string[] args)
{
Console.WriteLine("Write Something Into File:");
// File.Create("F:\\fuckyou.txt"); // 創建文件
String Context = Console.ReadLine();
File.WriteAllLines("F:\\fuckyou.txt",new String[] { Context}); //將一個字符串數組寫入文件
Console.WriteLine("該文件創建時間:"+ File.GetCreationTime("F:\\fuckyou.txt")+"\n"
+"文件寫入時間"+ File.GetLastWriteTime("F:\\fuckyou.txt")+"\n"+File.GetLastAccessTime("F:\\fuckyou.txt"));
Console.ReadKey();
}
运行:
Write Something Into File:
2021 ---- HOLY SHIT ----DUNGEON MASTER
該文件創建時間:2021/11/10 10:31:50
文件寫入時間2021/11/10 10:38:02
2021/11/10 10:31:50
这样就创建并写入了文件了,打开得到一下内容
2021 ---- HOLY SHIT ----DUNGEON MASTER
再测试一下文件夹
static void Main(string[] args)
{
Directory.CreateDirectory("F:\\新日暮里");
foreach (String dir in Directory.EnumerateDirectories("C:\\Program Files"))
{
Console.WriteLine(dir);
}
Directory.SetCreationTime("F:\\新日暮里", new DateTime(2077,12,31,11,22,33));
}
将所有的文件夹打印在控制台里
C:\Program Files\XXX
C:\Program Files\XXX
C:\Program Files\XXX
C:\Program Files\XXX
C:\Program Files\XXX
C:\Program Files\XXX
C:\Program Files\XXX
.........
并新建了文件夹
普通类
工厂类虽然简单,但是都必须要提供准确的文件路径作为参数,有的时候不是很方便,
这个时候就必须使用普通的文件和文件夹类了
在C#中,文件和文件夹类是FileInfo和DirectoryInfo,它们用于创建文件及文件夹对象,并提供了一套和工厂类相似的API.
这里以将对象写入文件举一个例子:
static void Main(string[] args)
{
FileInfo file = new FileInfo("F:\\fuckyou.txt");
FileStream fs = file.OpenWrite();
Person p1 = new Person("3605XXXXXX", "Stack", "skull");
byte[] buffer = ConvertToBuffer(p1); //将对象转化为字节数组,然后写入文件
fs.Write(buffer);
fs.Close(); //最后关闭流
}
public static byte[] ConvertToBuffer(Object obj)
{
byte[] buffer;
MemoryStream ms = new MemoryStream(); //使用BinaryFormatter转化成二进制byte
IFormatter iFormatter = new BinaryFormatter();
iFormatter.Serialize(ms, obj);
buffer = ms.GetBuffer();
ms.Dispose();
return buffer;
}
[Serializable] //必要
private class Person //如果要使用BinaryFormatter将对象转化为二进制
{ //对象的类必须实现序列化
public String pid { get; set; }
public String pname { get; set; }
public String paddress { get; set; }
public Person(String id,String name,String address)
{
pid = id;pname = name;paddress = address;
}
public Person()
{
}
}
打开目标文本文件查看
DFileAndIODemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null FileAndIODemo.Program+Person
<pid>k__BackingField<pname>k__BackingField<paddress>k__BackingField
3605XXXXXX Stack skull
感觉格式比较奇怪,但确实是吧所有的信息都序列化写入文件了…
再试一试DirectoryInfo,
DirectoryInfo directory = new DirectoryInfo("C:\\Program Files");
foreach(DirectoryInfo item in directory.GetDirectories())
{
Console.WriteLine(item.Name);
}
Console.ReadKey();
结果也同上:
7-Zip
XXXXX
XXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXX
XXXXXXX
XXX
XXX
...........
文件流的操作(文件的读写)
文件的读写必须通过文件流操作,它归属于流操作也就是IO,
在我比较熟悉的Java中,
流操作是一种典型的装饰模式的设计(在我的设计模式文章中有专门研究)
基础无疑是InputStream和OutputStream,
在它之上的装饰类有很多,各种Writer,Reader什么的(字符流),
还有DataIn&OutputStream,BUfferedIN&OutputStream,ObjectIn&OutputStream
ZipIn&OutStream…
包括FileIn&OutputStream都是它的的包装类.
分割线--------------------------------------------------------------------------------------
在C#中好像也使用了相同的设计模式,
但不分输入和输出(感觉有点别扭C++还用在用Cin>>和Cout<<)
FileStream的创建方法有很多:
public FileStream(SafeFileHandle handle, FileAccess access);
public FileStream(IntPtr handle, FileAccess access);
public FileStream(string path, FileMode mode);
public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize);
public FileStream(string path, FileMode mode, FileAccess access);
public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync);
public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize);
public FileStream(string path, FileMode mode, FileAccess access, FileShare share);
public FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize);
public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync);
public FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync);
public FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options);
其中涉及一些枚举类需要仔细看一看
FileMode
public enum FileMode
{
//创建新文件,已存在则会报错
CreateNew = 1,
//创建新文件
Create = 2,
//打开
Open = 3,
//打开或创建
OpenOrCreate = 4,
//打开现有文件,清除其内容。流指向文件的开头,保留文件的初始创建日期
Truncate = 5,
//追加
Append = 6
}
FileAccess
public enum FileAccess
{
//只用于读取
Read = 1,
//只用于写入
Write = 2,
//可读写
ReadWrite = 3
}
FileShare文件共享锁(不确定)
public enum FileShare
{
. //无锁
None = 0,
//读锁
Read = 1,
//写锁
Write = 2,
//读写锁
ReadWrite = 3,
//删除
Delete = 4,
//
// 摘要:
// Makes the file handle inheritable by child processes. This is not directly supported
// by Win32.
Inheritable = 16
}
如果不是多线程环境下则不要指定FileShare参数
现在测试一下流操作
FileStream fs = new FileStream("F:\\fuckyou.txt", FileMode.OpenOrCreate);
fs.Write(Encoding.Default.GetBytes("||11ll||1l|||------------|||||||"));
fs.Close();
||11ll||1l|||------------|||||||Demo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null FileAndIODemo.Program+Person <pid>k__BackingField<pname>k__BackingField<paddress>k__BackingField
3605XXXXXX Stack skull
或者可以从File或FileInfo中后期文件流,