《简介》
File 操作文件,静态类,对文件整体操作。拷贝,删除,剪切等
Directory 操作目录(文件夹),静态类。
DirectoryInfo 文件夹的一个“类”,用来描述一个文件夹对象(获取指定目录下的所有目录时返回的一个DirectoryInfo数组)
FileInfo 文件类,用来描述一个文件对象,获取指定目录下的所有文件时,返回一个FileInfo数组。
Path 对文件或目录的路径进行操作(很方便),它是一个静态类
Stream 文件流,抽象类,它是所有流的父类,下面是它的几个常用子类
FileStream 文件流 ,MemoryStream 内存流, NetworkStream网络流
StreamReader 快速读取文本文件(逐行读取)
StreamWriter 快速写入文本文件
GZipStrean 压缩流
《路径 | Path类》
[csharp] view plaincopy
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Path类
{
class Program
{
static void Main(string[] args)
{
string filepath = @"H:\音乐\无损\李玉刚\南飞雁.wav";
//现在我们要获取“南飞雁.wav”这个名字。我们可以这么获取。
Console.WriteLine(filepath.Substring(filepath.LastIndexOf(@"\")+1)); //输出:南飞雁.wav
//---------------------------现在我们有更好的方法------------------------------------
//1.获取文件名
Console.WriteLine(Path.GetFileName(filepath)); //输出:南飞雁.wav
//2.获取文件后缀
Console.WriteLine(Path.GetExtension(filepath)); //输出:.wav
//3.获取不带后缀的文件名
Console.WriteLine(Path.GetFileNameWithoutExtension(filepath)); //输出:南飞雁
//4.获取该路径的目录部分
Console.WriteLine(Path.GetDirectoryName(filepath)); //输出:H:\音乐\无损\李玉刚
//5.将路径中文件名的后缀改为.mp3
//注意:这里仅仅是修改的filepath这个字符串的后缀,与文件没有任何关系。他不会修改文件后缀
Console.WriteLine(Path.ChangeExtension(filepath, "mp3")); //输出:H:\音乐\无损\李玉刚\南飞雁.mp3
//6.将两个路径相加
string s1 = @"d:\abc\x";
string s2 = "hello.txt";
Console.WriteLine(Path.Combine(s1, s2)); //输出:d:\abc\x\hello.txt
//7.获取一个相对路径的绝对路径
Console.WriteLine(Path.GetFullPath("Program.cs")); //输出:D:\MVC\MvcTest\文件操作类\bin\Debug\Program.cs
// 获取当前操作系的统临时目录的路径 (就拿解压缩来举列子:当你打开一个压缩文件,注意此时你并没有点击解压缩,仅仅是打开一个压缩文件查看压缩文件的内 容,可是其实就在你打开压缩文件的时候,压缩软件就已经对这个文件进行解压了,因为只有解压了你才能看到文件的内容。因为你没有点击解压缩,仅仅是打开的 压缩文件,查看内容,所以解压缩软件会在系统的临时目录下生成一个临时目录来保存刚刚解压的文件,在用户查看压缩文件完毕后,关闭的时候,就解压缩软件就 会删除这个临时目录)
Console.WriteLine(Path.GetTempPath()); //输出:C:\Users\FB\AppData\Local\Temp\
//8.因为系统临时目录是公有的,大家都可以访问,并在里面创建一个临时目录,怎么保证各自创建的临时目录不重名呢?(答案是:由系统返回给我们一个临时目录名)
//创建磁盘上唯一命名的零字节的临时文件并返回该文件的完整路径。
Console.WriteLine(Path.GetTempFileName()); //输出:C:\Users\FB\AppData\Local\Temp\tmp828.tmp
}
}
}
《目录,文件夹 | Directory类》
[csharp] view plaincopy
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Directory类
{
class Program
{
static void Main(string[] args)
{
//操作目录类Directory
//-------------------------判断文件夹是否存在Exists()-----------------------
//4.判断指定路径下的文件夹是否存在,如果存在则为 true;否则为 false
Console.WriteLine(Directory.Exists(@"d:\1"));
//-------------------------创建目录CreateDirectory()-----------------------
//1.创建一些10个目录
for (int i = 1; i <= 10; i++)
{
//在D盘下的abc目录下创建10个文件夹,命名为1-10 (如果D盘下的abc文件夹存在,则在里面创建10个文件夹,如果不存在就创建这个abc文件夹后,再在里面创建10个文件夹)
Directory.CreateDirectory(@"D:\abc\" + i);
}
//-------------------------删除目录Delete()-----------------------
//3.删除一些目录
//删除目录的时候,如果指定的目录不存在则抛异常 :未能找到路径“D:\abc\11”的一部分。
Directory.Delete(@"D:\abc\11");
//删除目录的时候,如果指定的目录不为空则抛异常 :目录不是空的。(为了测试,我在1这个文件里放了一个文件)
Directory.Delete(@"D:\abc\1");
//删除指定的目录并删除该目录中的所有子目录和文件(即便指定目录里包含文件,指定目录及文件都会被删除)。
Directory.Delete(@"D:\abc\1", true);
//-------------------------移动目录Move()-----------------------
//3.移动(剪切)一些目录
//移动(剪切)不能跨磁盘操作,否则抛异常 : 源路径和目标路径必须具有相同的根。移动操作在卷之间无效。
//Directory.Move(@"D:\abc\1", @"F:\xyz");//错误的
//将D盘下的abc文件夹下的2这个文件夹及文件剪切到D盘,并将2这个文件夹重命名为1 ,如果1这个文件之前就已经存在,则抛异常:当文件已存在时,无法创建该文件。
Directory.Move(@"d:\abc\2", @"d:\1");
//-------------------------获取子目录,后代目录GetDirectories()-----------------------
//5.获取指定目录下的所有子目录(获取的是:直接子目录)
foreach (var i in Directory.GetDirectories(@"d:\abc"))
{
Console.WriteLine(i);
}
//5.1获取指定目录下的所有后代目录;(第二个参数是通配符,*表示所有后代目录,6*表示以6开头的所有后台目录,*中国*,表示包含“中国”的所有后代目录)
foreach (var i in Directory.GetDirectories(@"d:\abc", "*", SearchOption.AllDirectories))
{
Console.WriteLine(i);
}
//-------------------------获取子文件,后代文件GetFiles()-----------------------
//6获取指定目录下的所有子文件(获取的是:直接子文件)
foreach (var i in Directory.GetFiles(@"D:\常用软件"))
{
Console.WriteLine(i);
}
//6.1获取指定目录下的所有后代文件 (第三个参数表示搜索指定目录下的所有后代文件)
foreach (var i in Directory.GetFiles(@"D:\常用软件","*",SearchOption.AllDirectories))
{
Console.WriteLine(i);
}
}
}
}
《文件 | File 类》
[csharp] view plaincopy
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace File类
{
class Program
{
static void Main(string[] args)
{
//File 文件类
//-------------------------判断文件是否存在Exists()---------------------
//确定指定的文件是否存在。如存在则返回true;否则返回false
Console.WriteLine(File.Exists(@"d:\news\wowo.txt"));
//-------------------------创建文件Create()---------------------
//创建文件
File.Create(@"d:\news\hello.txt");
//在D盘创建一个utf8.txt文件,这个文件是用于写入 UTF-8 编码的文本。
File.CreateText(@"d:\utf8.txt");
//-------------------------删除文件Delete()---------------------
//删除指定文件(即便指定路径的文件不存在,也不会抛异常)
File.Delete(@"d:\news\hello.txt");
//-------------------------复制文件Copy()---------------------
//将d盘下的news文件夹下的wo.txt文件,复制到e盘下,命名为no.txt,true表示允许覆盖同名的文件。如果e盘之前就存在b.txt,那就就将其覆盖
File.Copy(@"d:\news\wo.txt", @"e:\no.txt",true);
//-------------------------剪切(移动)文件Move()---------------------
//将d盘下的news文件夹下的no.txt文件,剪切到e盘下,并重新将它命名为wo.txt (前提是e盘下之前就有a文件夹,否则抛异常:未能找到路径中的某个部分。)
File.Move(@"d:\news\no.txt",@"e:\aa\wo.txt");
//-------------------------替换指定文件的内容Replace()---------------------
//使用其他文件的内容替换指定文件的内容,这一过程将删除原始文件,并创建被替换文件的备份。
//将D盘下的1.txt文件内容【替换】2.txt文件的内容(这样2.txt里面将保存1.txt的内容),然后将1.txt文件删除。
File.Replace(@"d:\1.txt", @"d:\2.txt", @"d:\wowo.txt"); //既然2.txt的内容被1.txt替换掉了,那么第三个参数就是2.txt文件内容的备份
//---------------------文件的读取,与写入----------------------------
//打开一个文件,使用指定的编码读取文件的所有行,然后关闭该文件 (读取所有行,返回string[]数组)
string[] rows = File.ReadAllLines(@"D:\new\文档及资料\wo.txt", Encoding.Default);
//创建一个新文件,在其中写入指定的字符串数组,然后关闭该文件。 如果目标文件已存在,则覆盖该文件。
File.WriteAllLines(@"d:\wowo.txt", rows,Encoding.Default);
//打开一个文件,使用指定的编码读取文件的所有行,然后关闭该文件。 (读取所有文本内容,返回string字符串)
string file = File.ReadAllText(@"D:\new\文档及资料\wo.txt", Encoding.Default);
//创建一个新文件,在其中写入指定的字符串,然后关闭文件。 如果目标文件已存在,则覆盖该文件。
File.WriteAllText(@"d:\nono.txt", file,Encoding.Default);
//打开一个文件,将文件的内容读入一个字符串,然后关闭该文件。
byte[] fielStream = File.ReadAllBytes(@"D:\new\文档及资料\wo.txt");
//创建一个新文件,在其中写入指定的字节数组,然后关闭该文件。 如果目标文件已存在,则覆盖该文件。
File.WriteAllBytes(@"d:\haha.txt", fielStream);
//---------------------------文件内容的追加-------------------------
string[] fileContent= File.ReadAllLines(@"H:\code\bigtree\bigtree\log\2014-10-30.log",Encoding.Default);
// 在一个文件中追加文本行,然后关闭该文件。如果文件尚不存在,则创建该文件。
File.AppendAllLines(@"d:\wowo.txt", fileContent);
string fileTxt = File.ReadAllText(@"H:\code\bigtree\bigtree\log\2014-10-30.log", Encoding.Default);
//将指定的字符串追加到文件中,如果文件还不存在则创建该文件。
File.AppendAllText(@"d:\nono.txt", fileTxt,Encoding.Default);
//创建一个 System.IO.StreamWriter,它将 UTF-8 编码文本追加到现有文件。
StreamWriter sw= File.AppendText(@"d:\nono.txt");
}
}
}
《文件流 | FileStream类》
FileMode.Append (FileMode.Append 是优先打开文件,如文件不存在才创建新文件)
表示在现有的文件上追加内容(如果文件不存在则创建新文件,如果文件存在,就打开,并在文件末尾追加内容)
创建一个新文件。 如果文件已存在,就将它覆盖掉。
FileMode.Ceate (FileMode.Ceate 是创建新文件)
创建一个新文件。 如果文件已存在,就报异常,
FileMode.CreateNew
打开一个文件,如果文件存在则打开,如果文件不存在就创建一个新文件
FileMode.OpenOrCreate
打开一个的文件,如果文件不存在则报异常
FileMode.Open
打开一个文件,并立即将这个文件的内容清空(注意,打开这个文件的创建日期还是原来的那个日期)
FileMode.Truncate
----------------------------------------
上面说了FileMode.Append 是打开文件,文件不存在就创建文件,并在文件末尾追加内容
而FileMode.OpenOrCreate 也是打开文件,文件不存在就创建文件。那么他们之间的区别是什么呢?
答案:他们的的区别是取决于第三个参数FileAccess
FileAccess.Read 对文件的读访问。 可从文件中读取数据,不能写入数据(即:只能读不能写)
FileAccess.Write 对文件的写访问。 可将数据写入文件,不能读取文件 (即:只能写不能读)
FileAccess.ReadWrite 对文件的读访问和写访问。 可从文件读取数据和将数据写入文件。(即:能读能写)
[csharp] view plaincopy
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 文件流FileStream
{
class Program
{
static void Main(string[] args)
{
//File类的方法: 快速得到文件流
FileStream fsA = File.Open(@"D:\wowo.txt",FileMode.OpenOrCreate);
FileStream fsB = File.OpenRead(@"D:\wowo.txt");
FileStream fsC = File.OpenWrite(@"D:\wowo.txt");
FileStream fsD = new FileStream(@"D:\wowo.txt", FileMode.OpenOrCreate);
//----------------------------------文件流的使用方式---------------------------------------
string str = "中国美国德国俄罗斯";
//将一个字符串变成一个字节数组
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(str);
//将一个字节数组转换成一个字符串
string msg = System.Text.Encoding.UTF8.GetString(bytes);
//文件流不能操作字符串,文件流操作的都是字节
//-----------------------------------通过FileStream来写文件-----------------------------------
//文件流的使用步奏
//1.创建文件流 (fsWrite是文件流,不是二进制数组)
FileStream fsWrite = new FileStream(@"d:\wowo.txt", FileMode.Create, FileAccess.Write);
//2.使用文件流,执行往文件写入数据的操作
string msgB = "今天是个好日子。lalala....";
byte[] bytesB = System.Text.Encoding.UTF8.GetBytes(msgB);
//3.表示将指定的字节数组中的内容写入到文件(其实此时并没有真正的写入,只是放到缓冲区了)
fsWrite.Write(bytesB, 0, bytesB.Length);
//4.将缓冲区的所有数据立即写入到文件中,然后清空缓冲区
fsWrite.Flush();
//5.关闭文件流,并释放资源 (注意:关闭后是可以再次打开的)
fsWrite.Close();
//6.销毁文件流,释放资源 (注意:销毁后就无法再打开了)
fsWrite.Dispose();
// 其实大多时间我们都不会写fsWrite.Flush()和fsWrite.Close();这两个方法,一般只需要些 fsWrite.Dispose();就可以了。因为当你调用fsWrite.Dispose(); 的时候,它内部会调用 fsWrite.Close(),而fsWrite.Close();内部又会去调用fsWrite.Flush();
//如果实现了IDispose接口的类直接用using就行了。using结束的时候会自动帮我们调用Dispose()方法
//-----------------------------------通过FileStream来读文件-----------------------------------
//使用FileStream文件流读取文本文件的时候不要,指定编码,因为编码是在将byte[]数组转换为字符串的时候才需要使用编码,而这里是直接读取到byte[],所以无需编码
//1.创建文件流(fsRead是文件流,不是二进制数组)
using (FileStream fsRead = new FileStream(@"d:\wowo.txt", FileMode.Open, FileAccess.Read))
{
byte[] bytesC = new byte[fsRead.Length];//创建一个二进制数组,长度为fsRead这个流的长度
fsRead.Read(bytesC, 0, bytesC.Length); //从流中读取字节,然后保存到bytesC这个二进制数组中
string strC = System.Text.Encoding.UTF8.GetString(bytesC); //将bytesC这个二进制数组转换成字符串
Console.WriteLine(strC);
//注意:其实我们在根据文件流的总字节数,即长度,来创建bytesC这个二进制数组,用来存放“d:\wowo.txt”这个文件的二进制字节数据,其实这样对于小文件来说是适用的,但是对于大文件来说就不适用了,因为这种方式会将文件内容一次性读取到bytesC中
}
Console.WriteLine("OK");
Console.ReadKey();
}
}
}
FileStream文件流的综合使用
[csharp] view plaincopy
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 文件流FileStream
{
class Program
{
static void Main(string[] args)
{
//------------------------------FileStream的综合应用,大文件的拷贝-----------------------------------
string source_file=@"G:\最美的地球.flv";
string des_file=@"D:\最美的地球.flv";
using (FileStream fsReadD = new FileStream(source_file, FileMode.Open, FileAccess.Read))
{
using(FileStream fsWriteD=new FileStream(des_file,FileMode.Create,FileAccess.Write))
{
byte[] bytesD = new byte[1024 * 1024 * 5];
//Read()方法的返回值是本次实际读取到的字节个数
int i = fsReadD.Read(bytesD, 0, bytesD.Length);
while(i>0)
{
//将bytesD这个字节数组的数据写入到D:\最美的地球.flv 这个文件
fsWriteD.Write(bytesD, 0, i);
//注意这个i不能少; 当将bytesD这个字节数组的数据写入到D:\最美的地球.flv 这个文件后,再次从上次读取结束的位置接着读取数据保存到bytesD中,知道读取完毕(完毕即:i<=0)
i= fsReadD.Read(bytesD, 0, bytesD.Length);
//有人会问,它怎么会知道从上次读取结束的位置接着向后读取字节数据呢,而不是从文件的开始位置读取呢?:答案是:每个文件流内部都有一个Position属性,这个属性的值就获取或者设置此流的当前位置。//long a= fsReadD.Position;
}
}
}
Console.WriteLine("OK");
Console.ReadKey();
}
}
}
题外:
[csharp] view plaincopy
//平常我们创建FileStream对象的时候是这样创建的: FileStream fs=new FileStream(参数);
//但是内次new一下很麻烦,当你要读取一个文件的文件流的话 这时候没有必要这样new我们有简单的方法
//FileStream fsRead= FileStream.OpenRead("a.txt") 当你调用OpenRead()这个方法的时候,
//它内部会给你new一个 FileStream对象;并且会初始化设置那些各种各样的参数,省的我们去设置了
//比如:OpenRead这个静态方法源代码是这样的:
public static FileStream OpenRead(string path)
{
return new FileStream(path,FileMode.open,FileAccess.Read,FileShare.Read);
}
//比如:OpenWrite这个静态方法的源代码是这样的:
public static FileStream OpenWrite(string path)
{
return new FileStream(path,FileMode.Write,FileAccess.Write,FileShare.None);
}
//但是如果你在循环里面,你千万别这样用,因为他们每次调用OpenRead或OpenWrite 都会new一个对象,
//建议最好在循环外面创建一个对象来读:比如这样:FileStream fs=new FileStream(参数);
《StreamReaded与StreamWriter》(主要用来操作文本文件合适,逐行读写)
因为大文本文件也希望一点一点的来读,如果用File.ReadAllText ,或者使用File.ReadAllLines来读取,那么它势必会一下把大文本文件的整个内容都一次性读到一个字符串,或字符串数组里(其实都是先写到 内存中的,这样就会撑爆内存),然后写到到另外一个大文本文件中,这样也就没法解决大文件读取的问题。
那如果我们用FileStream来读取呢?,但是如果你要用FileSteam,就必须要把数据一次性读取到一个byte[]数组里,然后将这个字节数 组写入到其他的文本文件。它不能像其他的大文件(主要这里的大文件不是指大的文本文件)那样读一部分,写入一部分,直到读完整个大文件,和写入整个大文 件。(例如;像电影这样的大文件,我通过FileStream 来读取,我读一点写一点,当我读一点的时候,我记下了上次读到第几个字节,这次再从第几个字节再读取,相当于累加起来,最后组成一个电影)
但是对于文本文件来说就存在一个问题,比如说: 假如 a你好a你好a 是一个大文本文件,我想一点一点的来读取这个大文本文件,于是我决定以4个字节为一部分来读(即读完4个字节,就将它放入到byte[]数组中,然后将这 个byte[]数组写入到一个字符串中,这样问题就来了。我们知道汉字是占用两个字节的,我现在要以4个字节为一组来读取 a你好a你好a 这个大文本文件, 当我读到“好”的时候,发现这个“好”只读到一半就已经满4个字节了。然后将这4个字节写入到字符串,可是这4个字节并不能组成 a你好 ,前面的a你 可以组成,可是后面那个“好”却组不成了,因为只有1个字节,而这1个字节通过转码的时候就乱码了。)
而StreamRead 既能一点一点的来读取文本文件,又能正常的读取字符串来。它的内存里始终只有一行的数据占用,不会太占用内存(StreamReaded与StreamWriter不适合文本文件外的大文件读取,比如电影文件)
StreamRead 类有两个方法
ReadToEnd () 用于从当前位置一直读到最后,内容打的话会占内存,每次调用都往下走,不能无意中调用了两次
ReadLine() 一行一行的读取,如果到了末尾,则返回null。
[csharp] view plaincopy
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StreamReaded与StreamWriter
{
class Program
{
static void Main(string[] args)
{
//StreamReader用来逐行读取文本,直到文件的末尾
using (StreamReader sr = new StreamReader(@"D:\企业管理系统\Itcast.CMS\Itcast.CMS.WebApp\Itcast.CMS.WebApp.csproj",Encoding.Default))
{
//StreamWriter用来逐行写入文本
using (StreamWriter sw = new StreamWriter(@"d:\wowo.txt",true,Encoding.Default))
{
// 获取一个值,该值表示当前的流位置是否在流的末尾。
while (!sr.EndOfStream)
{
//将读取到的字节数据写入到d:\wowo.txt
sw.WriteLine(sr.ReadLine());
}
//或者下面这样写法
//string line = null;
//while ((line = sr.ReadLine()) != null)
//{
// sw.WriteLine(sr.ReadLine());
//}
}
}
Console.WriteLine("oK");
Console.ReadKey();
}
}
}