(1)
(2)
(3)
(4)
(5)
(6)
(1),删除目录
(2)
(3),创建文件夹
(4),得到一个目录下的子目录
(5) ,通配符查找目录下的子目录
(6) ,得到一个目录下的文件
(7) ,通配符查找目录下的文件
(8) ,得到目录的父目录
(1),修改文件的后缀
(2),将两个路径合成一个路径
(3),得到文件的路径名
(4) ,得到文件的扩展名
(5),得到文件路径的文件名部分
(6),得到去除扩展名的文件名
(7) ,得到文件的全路径
(8) ,得到一个唯一的临时文件名(*)
(9)
(10),得到当前exe的绝对路径
练习:(读取配置的时候经常用到)
(1),从流中读取字节块并将该数据写入给定缓冲区中
(2)练习:
(1)
(2)
(1)
(2)
(3)
6.3.1 GZipStream
6.3.2 GZipStream
1、文件操作:File
文本文件编码,文本文件有不同的存储方式,将字符串以什么样的形式保存为二进制,这个就是编码,UTF-8、ASCII、Unicode等,如果出现乱码一般就是编码的问题,文本文件相关的函数一般都有一个Encoding类型的参数,
取得编码的方式:Encoding.Default、Encoding.UTF8、Encoding.GetEncoding("GBK")。以什么编码存就以什么编码取就不会乱码。
File类的常用静态方法:
(1)void AppendAllText(string path, string contents),将文本contents附加到文件path中
(2)bool Exists(string path)判断文件path是否存在
static void Main(string[] args)
{
string s = "asasas";
if (File.Exists("H:/1.txt"))
{
Console.WriteLine("文件已经存在,是否覆盖?(Y/N)");
string o = Console.ReadLine();
if (o=="y")
{
File.WriteAllText("H:/1.txt",s);
}
}
}
结果
(3)string[] ReadAllLines(string path)
读取文本文件到字符串数组中
string[] s = File.ReadAllLines("H:/1.txt");
foreach (var mw in s)
{
Console.WriteLine(mw);
}
Console.ReadKey();
读取文本文件到字符串中
(5)void WriteAllText(string path, string contents)将文本contents保存到文件path中,会覆盖旧内容。
(6)WriteAllLines(string path,string[] contents),将字符串数组逐行保存到文件path中,会覆盖旧内容。
2、目录操作(文件夹操作):Directory
Directory类的常用静态方法:(目录就是文件夹)
(1)void Delete(string path, bool recursive)删除目录, recursive表示是否递归删除,如果recursive为false则只能删除空目录
Directory.Delete("H:/test1",true);
(2)bool Exists(string path)
判断目录是否存在
(3)CreateDirectory:创建文件夹
问题:需要在H:/temp1/a.txt写入字符串aabbccdd.
解析:没有目录。
string s = "aabbccdd";Directory.CreateDirectory(@"H:\temp1");File.WriteAllText("H:/temp1/a.txt",s);
(4)string[] GetDirectories(string path)
得到一个目录下的子目录
string[] files = Directory.GetDirectories(@"c:\");
foreach (string file in files)
{
Console.WriteLine(file);
}
Console.ReadKey();
通配符查找目录下的子目录
(6)static string[] GetFiles(string path)得到一个目录下的文件
string[] files = Directory.GetFiles(@"c:\");
foreach (string file in files)
{
Console.WriteLine(file);
}
Console.ReadKey();
通配符查找目录下的文件
string[] strings = Directory.GetFiles(@"G:\电影\", "*.rmvb", SearchOption.AllDirectories);
foreach (string s in strings)
{
Console.WriteLine(s);
}
Console.ReadKey();
得到目录的父目录
3.Path类常用静态方法
(1)string ChangeExtension(string path, string extension) (*)
修改文件的后缀,“修改”支持字符串层面的,没有真的给文件改名
string s = Path.ChangeExtension(@"C:\temp\F3.png", "jpg")
(2)tring Combine(string path1, string path2)
将两个路径合成一个路径,比用+好,可以方便解决是不是加斜线的问题,自动处理路径分隔符的问题 string s = Path.Combine(@"c:\temp","a.jpg")(3)string GetDirectoryName(string path) (*)
得到文件的路径名。Path.GetDirectoryName(@"c:\temp\a.jpg")(4)string GetExtension(string path)
得到文件的扩展名,例如用来限制用户上传exe的功能
(5)string GetFileName(string path)
得到文件路径的文件名部分
(6)string GetFileNameWithoutExtension(string path)
得到去除扩展名的文件名
(7)string GetFullPath(string path)
得到文件的全路径。”.\”当前路径,”..\”上一级路径,”..\..\”上一级的上一级
(8)string GetTempFileName()
得到一个唯一的临时文件名(*)
(9)string GetTempPath()
得到临时文件夹的路径(*)
(10)得到当前exe的绝对路径。Assembly.GetExecutingAssembly(),不要用Directory.GetCurrentDirectory(),这个可能会变(使用OpenFileDialog或者SetCurrentDirectory())。(*)解决Access文件路径的问题。引用反射
string loc = Assembly.GetExecutingAssembly().Location;
Console.WriteLine(loc);
Console.ReadKey();
练习:读取和File同目录下的mm.txt文档内容(读取配置的时候经常用到)
4.文件流
1.拷贝文件的两种方式:将源文件内容全部读到内存中,再写到目标文件中;读取源文件的1KB内存,写到目标文件中,再读取源文件的1KB内存,再写到目标文件中……。第二种方式就是一种流(Stream)的操作。
2.用File.ReadAllText、File.WriteAllText进行文件读写是一次性读、写,如果文件非常大会占内存、慢。需要读一行处理一行的机制,这就是流(Stream)。Stream会只读取要求的位置、长度的内容。
FileStream.Read ( )方法 :从流中读取字节块并将该数据写入给定缓冲区中。
Stream.Read(Byte[ ], Int32, Int32)
array类型:System.Byte[ ] 此方法返回时包含指定的字节数组,数组中 offset 和 (offset + count - 1) 之间的值被从当前源中读取的字节替换。
offset类型:System.Int32 array 中的字节偏移量,将在此处开始读取字节。
count类型:System.Int32 最多读取的字节数。
3.就像SqlConnection一样,Stream不会将所有内容一次性读取到内存中,有一个指针,指针指到哪里才能读、写到哪里。
using (FileStream a = new FileStream(@"h:\1111111.7z", FileMode.Create))
{
using (FileStream fs = new FileStream(@"h:\boce1.7z", FileMode.Open))
{
byte[] bytes = new byte[1024];
int readLength;//实际读出来的长度
while ((readLength = fs.Read(bytes, 0, bytes.Length)) > 0)
{
a.Write(bytes, 0, readLength);
}
}
}
4.流有很多种类,文件流是其中一种。FileStream类new FileStream(“c:/a.txt”, filemode, fileaccess)后两个参数可选值及含义自己看。 FileStream可读可写。可以使用File.OpenRead、File.OpenWrite这两个简化调用方法。
5.练习:文件加密(每一位用255-r)。加密就是解密,解密就是加密。
1112.7z又可以打开了
private void button1_Click(object sender, EventArgs e)
{
using (FileStream input = new FileStream(textBox1.Text, FileMode.Open))
{
using (FileStream output = new FileStream(textBox2.Text, FileMode.Create))
{
byte[] bytes = new byte[1024 * 1024]; //1M
int readLength;
while ((readLength = input.Read(bytes, 0, bytes.Length)) > 0)
{for (int i = 0; i < readLength; i++) { bytes[i] = (byte)(255 - bytes[i]); }
output.Write(bytes,0,bytes.Length);
}
}
}
}
6.byte[]是任何数据的最根本表示形式,任何数据最终都是二进制。
7.Write用于向当前位置写入若干字节,Read用户读取若干字节。(*)每次Read、Write指针都会自动后移。
5.如何在程序中访问Access写相对路径——(*了解)
1、OleDbConnection的连接字符串必须是绝对路径,ADO.Net提供了一个“特殊字符串” DataDirectory表示“数据库文件夹”,如果是Winform程序DataDirectory表示当前运行的exe的文件夹,对于ASP.Net程序DataDirectory表示当前项目的App_data文件夹。
2、在WinForm中如果不修改DataDirectory,则运行时修改的是exe同文件夹下的mdb,而开发人员看的是项目中的mdb。而正式运行的时候则需要程序操作exe同文件夹下的mdb,因此通过代码修改DataDirectory。代码见备注,这个代码要放到程序最开始运行一次即可。如果是WinForm程序则要放到Main最开始
string dataDir = AppDomain.CurrentDomain.BaseDirectory;
if (dataDir.EndsWith(@"\bin\Debug\")
|| dataDir.EndsWith(@"\bin\Release\"))
{
dataDir = System.IO.Directory.GetParent(dataDir).Parent.Parent.FullName;
AppDomain.CurrentDomain.SetData("DataDirectory", dataDir);
}
6.文件流高级
(1)文件流的Flush、Close、Dispose。缓冲区
string s = "hello";
byte[] bytes = Encoding.UTF8.GetBytes(s);
fs.Write(bytes, 0, bytes.Length);//FileStream会把数据写入缓冲区
//fs.Flush();//强制把缓冲区的中数据写入文件
fs.Close(); //会把没写入缓冲区的数据写入文件(Flush)再关闭
//Dispose();//会调用colse(),所以调用stream时用using最保险
这样可以,最好还是用using
using (FileStream fs = new FileStream(@"H:\1.txt", FileMode.Create))
{
string s = "hello";
byte[] bytes = Encoding.UTF8.GetBytes(s);
fs.Write(bytes, 0, bytes.Length);//FileStream会把数据写入缓冲区
//fs.Flush();//强制把缓冲区的中数据写入文件
//fs.Close(); //会把没写入缓冲区的数据写入文件(Flush)再关闭
//Dispose();//会调用colse(),所以调用stream时用using最保险
}
(2)更方便的用法:File.OpenRead,File.OpenWrite,内部还是new。
FileStream ds = File.OpenRead(@"H:\1.txt");//FileMode.Open
FileStream ds = File.OpenWrite(@"H:\1.txt");//FileMode.Create
(3)Stream类是FileStream类的父类,有MemoryStream(内存流)、GZipStream (压缩解压流)、CryptoStream (加密流), GZipStream 、 CryptoStream 是装饰者模式的应用。尽量只操作父类Stream。
6.3.1 压缩
string str = "亲,你好吗?亲,你好吗?亲,你好吗?亲,你好吗?";
for (int i = 0; i < 20; i++)
{
str += str;
}
using (FileStream fs = File.OpenWrite(@"h:\2.txt"))
{
byte[] tBytes = Encoding.UTF8.GetBytes(str);
fs.Write(tBytes, 0, tBytes.Length);
}
点击压缩后,
string str = "亲,你好吗?亲,你好吗?亲,你好吗?亲,你好吗?";
for (int i = 0; i < 20; i++)
{
str += str;
}
using (FileStream fs = File.OpenWrite(@"h:\2.txt"))
{
//CompressionMode.Compress 压缩using (GZipStream zip = new GZipStream(fs,CompressionMode.Compress))
{
byte[] tBytes = Encoding.UTF8.GetBytes(str);zip.Write(tBytes, 0, tBytes.Length);
}
}
6.3.2 解压缩
using (FileStream fs = File.OpenRead(@"h:\2.txt"))
{
using (GZipStream zip =new GZipStream(fs,CompressionMode.Decompress))
{
using (FileStream outstream = File.OpenWrite(@"h:\2unzip.txt"))
{
int byteaRead;
byte[] bytes=new byte[1024];
while ((byteaRead = zip.Read(bytes,0,bytes.Length))>0)
{
outstream.Write(bytes,0,byteaRead);
}
}
}
}
(4)只读写文本,不用每次都写代码进行复杂的代码,编写自己的MyStreamReader、编写自己的MyStreamWriter。实现复用。
7.StreamReader
和StreamWriter类似, StreamReader简化了文本类型的流的读取。
ReadToEnd用于从当前位置一直读到最后,内容大的话会占内存;每次调用都往下走,不能无意中调用了两次
ReadLine读取一行,如果到了末尾,则返回null。private void button1_Click(object sender, EventArgs e)
{
//StreamReader可以读文件流,压缩流,内存流等等
using (Stream fs = File.OpenRead(@"H:\temp1\a.txt"))
{
string s = "";
//因为StreamReader负责在byte[]和string之间转换,
//所以需要指定编码(Encoding.UTF8)
using (StreamReader stream = new StreamReader(fs,Encoding.UTF8))
{
//ReadLine读取一行数据,指针自动下移
//while ((s = stream.ReadLine()) != null)
//{
// MessageBox.Show(s);
//}
s = stream.ReadToEnd();
MessageBox.Show(s);
}
}
}
8.StreamWriter
Stream把所有内容当成二进制来看待,如果是文本内容,则需要程序员来处理文本和二进制之间的转换。
用StreamWriter可以简化文本类型的Stream的处理
StreamWriter是辅助Stream进行处理的
private void button2_Click(object sender, EventArgs e)
{
using (Stream stream = File.OpenWrite(@"H:\temp1\a.txt"))
{
string s = "";
using (StreamWriter writer =new StreamWriter(stream,Encoding.UTF8))
{
writer.WriteLine("Hello");
writer.WriteLine("World");
writer.WriteLine("!啊");
}
}
}
StreamWriter对Stream进行了包装,调一下writer.WriteLine背后帮我们做了把字符串转换为二进制的工作。
9.WebClient的流操作
WebClient OpenRead方法打开一个读取流(ReadLine好像有Bug);OpenWrite方法打开一个写入流。
案例:使用WebClient分析读取http服务器上的Excel文件,不用中间文件。基于流方式进行操作的好处就是不用中间文件,没有安全性问题、没有文件冲突问题。开发复杂一点程序的原则就是步步为营,不要想着一次写出来,比如这个案例就可以分解为:读取数据库、创建Excel、上传Excel三步,所以先读取数据库,然后WriteLine看看数据有没有被正确的读出来,ok再开发生成Excel的功能,先生成到FileStream中,成功了再最后完成上传到FTP的功能。这也是迭代的开发方式File.ReadAllLines(),Stream、FileStream、StreamWriter之间的关系,如何分析Xls等二进制数据
10.对象序列化
对象序列化是将对象(比如Person对象)转换为二进制数据,反序列化是将二进制数据还原为对象。对象是稍纵即逝的,不仅程序重启、操作系统重启会造成对象的消失,就是退出函数范围等都可能造成对象的消失,序列化/反序列化就是为了保持对象的持久化。就像用DV录像(序列化)和用播放器播放(反序列化)一样。
BinaryFormatter类有两个方法:void Serialize(Stream stream, object graph)对象graph序列化到stream中object Deserialize(Stream stream)将对象从stream中反序列化,返回值为反序列化得到的对象练习:将几个int、字符串添加到ArrayList中,然后序列化到文件中,再反序列化回来。不是所有对象都能序列化,只有可序列化的对象才能序列化,在类声明上添加[Serializable],对象的属性、字段的类型也必须可序列化。反序列的项目中必须有同样的类,否则不能反序列化。未完待续。。