第七章档案读写与管理

 
第七章 档案读写与管理
「凡走过必留下痕迹」,所以生命才会有真理,生命也才会不平凡。
程序也是一样,若我们写好的程序,其最终的结果若是不留下任何痕迹,那么它的利用性就不高,而要让程序留下痕迹,供后人利用,则非透过档案的读写不可。
C# 要读写档案,必须引用一个新的命名空间:「 System.IO 」,若要指定编码方式,则另需引用「 System.Text 」这个命名空间,其用法如下:
using System.IO;
using System.Text;
  放的位置,可以是在「 using System; 」这个叙述之前或之后皆可,以后若有引用新的命名空间,其放置的位置也是这样的原则,或者说,命名空间的引用不在乎彼此顺序。
 
StreamWriter 档案写入法
档案的写入基本的三个步骤:开启、写入、关闭。
开启写入档案的语法
StreamWriter 档案对象 = new StreamWriter( 文件名称 , 是否接续 , 编码方式 );
 
其中「档案对象」是一个名称,其命名方式和变量名称规则一样,而文件名称可以是一个字符串或一个字符串变量,不管其内容为何,都必须可以让系统接受为文件名称,也可以包含资料夹名称,例如以下是一些合法的
"test"
"exam.txt"
"d://work//test.txt"
至于「是否接续」,是一个布尔值,可以是「 true 」或「 false 」,若是「 true 」,表示写入的资料会接续在被写入的档案原有的数据的后面,若为「 false 」,则被写入的档案原有的内容会被清空后,再写入数据,而编码方式如表 7-1 所示,若省略编码方式,则采用 系统现行的编码方式
而数据要写入档案则和 Console 模式差不多,方法如下
档案对象 .WriteLine( 输出字符串 );
档案对象 .Write( 输出字符串 );
最后,若档案已经不再有写入的动作时,则必须加以关闭,以后才能要读取或更改其属性,关闭的语法为:
档案对象 .Close( );
 
7-1 C# 档案编码方式
编码方式
说明
System.Text.Encoding.Default
以系统现行的编码方式
System.Text.Encoding.ASCII
ASCII Code 作为编码方式
System.Text.Encoding.BigEndianUnicode
Big-Endian Unicode 作为编码方式
System.Text.Encoding.Unicode
Unicode 作为编码方式
System.Text.Encoding.UTF7
UTF7 作为编码方式
System.Text.Encoding.UTF8
UTF8 作为编码方式
注:实用上若已 using System.Text ,则可以省略表中的 System.Text
 
EX 7-1 请在一个新的 c:/test.txt 写入 123 456 789 」、「 987 654 321 」于两行,采用 unicode 编码。
【解】
StreamWriter MYFILE = new StreamWriter( "c://test.txt" , false, Encoding.Unicode );
MYFILE.WriteLine( " 123 456 789 " );
MYFILE.WriteLine( "987 654 321 " );
MYFILE.Close( );
执行后以记事本打开 c:/test.txt ,内容如下,刚刚的数据都写入了。
 
EX 7-2 请在 EX7-2 c:/test.txt 的后面写入 「结束了」。
【解】
StreamWriter MYFILE = new StreamWriter("c://test.txt",true, Encoding.Unicode);
MYFILE.WriteLine(" 结束了 ");
MYFILE.Close( );
执行上面的程序后以记事本打开 c:/test.txt ,内容如下,可以发现除了原先的数据,另外多了一行「 结束了 」。
 
 
EX7-3 产生 100 个介于 1 10000 的随机数,每 10 个一列,整齐地写入 c:/number.txt
【解】
StreamWriter NUMFILE = new StreamWriter("c://number.txt",false) ;          
Random NUM = new Random();
int i;
for (i=1; i<101;i++)
{
       NUMFILE.Write("{0,7:D}",NUM.Next(1,10001));
       if (i%10==0)NUMFILE.WriteLine();
}
NUMFILE.Close( );
 
 
StreamReader 档案读取法
档案的读取和写入的方式有一点像, 基本的三个步骤:开启、读取、关闭。
开启读取档案的语法:
StreamReader 档案对象 = new StreamReader( 文件名称 , 编码方式 );
 
而数据要写入档案则和 Console 模式差不多,方法如下 [1] [1]
档案对象 .ReadLine();
档案对象 . .ReadToEnd ();
 
最后,若档案已经不再有读取的动作时,则必须加以关闭,以后才能被读取、写入或更改其属性,关闭的语法为:
 
档案对象 .Close( );
 
EX7-4 EX7-3 产生的 c:/number.txt 的内容读取,并显示于屏幕。
【解法一】逐行读取,前面我们已经知道写入 10 行,因此可以用循环逐行读入。
StreamReader MYREADER = new StreamReader("c://number.txt");
int i;
string s;
for (i=1;i<11;i++)
{
       s=MYREADER.ReadLine();
       Console.WriteLine(s);
}
 
【解法二】一次全部读取
StreamReader MYREADER = new StreamReader("c://number.txt");
int i;
string s;
s=MYREADER.ReadToEnd();
Console.WriteLine(s);
MYREADER.Close();
以上两个解法输出结果都相同,如图 7-4 所示。
 
逐行读取和一次读取各有应用上的需求,当字符串需要逐行处理时,还是以逐行读入较妥适,例如以下的例子:
EX7-5 请分不同行输出 EX7-3 c:/number.txt 里的第一列数字
【解】读入一行后以字符串处理的技术将个别数字字符串输出
StreamReader MYREADER = new StreamReader("c://number.txt");
int i;
string s;
string [] num;
s=MYREADER.ReadLine();
num=s.Split(' ');// 以空白分割子字符串
for (i=0;i<num.Length;i++)
if (num[i].Trim()!="")Console.WriteLine(num[i]);// 不打印空白字符串
MYREADER.Close();
 
7-4
7-5 分不同行打印 mumber.txt 里的第一列的数字
 
二进制 档案写入法
数据串流( data stream )是把数据看成「字节」的连接,比较严谨的数据库,都应该是以串流的型态来读写。在 EX7-5 里,因为是以一行的方式读入字符串,再以字符串处理的方式解析内容,因此会花需多时间在字符串的解析,所以档案读取效率不佳。例如一个 32 位的整数写入档案,应该占档案 32 位,当我们读取数据时,若确认下一比的数据是 32 位的整数,那么只需精准地读入 32 位,再转换为整数即可,所以效率高。
C# 提供了宣告串流档案的方法,
串流档案的以 FileStream 宣告,
FileStream 串流档案对象 =new FileStream( 文件名称 , 档案建立模式 );
 
其中「串流档案对象」表示该档案将要以字节型态写入,而「文件名称」和前面所叙一样,至于「档案建立模式」的功用如表 7-1 所示。
 
档案建立模式
说明
FileMode.Append
在档案存在时开启它并搜寻至档案末端,或建立新档案。
FileMode.Create
指示操作系统应该建立新档案。如果档案已经存在,将覆写此档案。
FileMode.CreateNew
指示操作系统应该建立新档案。
FileMode.Open
指示操作系统应该开启存在的档案。
FileMode.OpemOrCreat
指示操作系统,如果档案存在应该开启档案;否则,应该建立新的档案。
 
虽然串流档案对象也有自己的读写档案的方式,但是太过于麻烦,因此有兴趣的读者请自行研究,作者不另再说明。
当串流档案宣告完成后,可以利用 BinaryWriter BinaryReader 来读写,其中宣告二进制写入的方式是
BinaryWriter 二进制档案对象 = new BinaryWriter ( 串流档案对象 );
 
而宣告二进制读取的方式是
BinaryReaderr 二进制档案对象 = new BinaryReader ( 串流档案对象 );
 
写入数据的方法
二进制档案对象 .Write ( 数值或字符串数据 );
 
读取数据的方法依照被写入数据的数据型态而定
二进制档案对象 . 读入数据类型 ();
其中读入数据类型 ReadInt32 ReadDouble ReadString ,如表 7-2 所示,仅列举部分读者可依数据型态种类自行尝试其它方法。
 
 
EX7-6 int a=1, double b=2.5, string s=”abcde” 以二进制方式写入和读取。
int a=1;
double b=2.5;
string c="abcde";
FileStream WRITEFILE = new FileStream("c://binary.txt",FileMode.Create); // 注意 FileMode
BinaryWriter BINWRITE = new BinaryWriter(WRITEFILE );
BINWRITE.Write(a);
BINWRITE.Write(b);
BINWRITE.Write(c);
BINWRITE.Close();
WRITEFILE.Close();
FileStream READFILE = new FileStream("c://binary.txt",FileMode.Open);// 注意 FileMode
BinaryReader BINREAD = new BinaryReader(READFILE);
int d=BINREAD.ReadInt32();
double e=BINREAD.ReadDouble();
string f=BINREAD.ReadString();
Console.WriteLine("{0} {1} {2}",d,e,f);
READFILE.Close();
BINREAD.Close();
 
 

7-2 二进制档案读入数据类型的方法和其它方法(部分列举)
方法
说明
用法(假设二进制档案对象是 a
Close
关闭目前的读取器 (Reader) 和基础数据流。
a.Close();
PeekChar
传回下一个可用字符,而不前移字节或字符的位置。
char b=(char) a.PeakChar();
ReadBoolean
自目前数据流读取 Boolean 值,并将数据流中目前的位置往前移一个字节。
bool c=a. ReadBoolean();
ReadByte
自目前数据流读取下一个字节,并将数据流中目前的位置往前移一个字节。
byte c=a.ReadByte();
ReadBytes
自目前数据流读取指定数目字节到字节数组,并将目前位置往前移指定数目字节。
byte [] d= a.ReadBytes(5);// 读入 5 个字节
ReadChar
按照所使用的 Encoding 和从数据流读取的特定字符,自目前数据流读取下一个字符,并将数据流中目前的位置往前移。
char b=(char) a. ReadChar ();
ReadChars
按照所使用的 Encoding 和从数据流读取的特定字符,自目前数据流读取指定数目字符,再将数据传回字符数组,并将目前位置往前移。
char [] e =a. ReadChars(2);// 读入 2 个字节
ReadDouble
自目前数据流读取八字节浮点数值,并将数据流目前位置前移八个字节。
double f =a. ReadDouble();
ReadInt32
自目前数据流读取四字节带正负号的整数,并将数据流目前位置前移四个字节。
int g= a.ReadInt32();
ReadSingle
自目前数据流读取四字节浮点数值,并将数据流目前位置前移四个字节。
float h =a. ReadSingle();
ReadString
自目前数据流读取字符串。字符串会以长度为前导符,每次以 7 位编码为一整数。
string s =ReadString();
 
档案的管理
在程序的进行中,有时候必需对某一些档案做处理,例如侦测档案的状态、改变档案的属性、删除档案、复制档案等,在进行这些操作时,同样必需用到「 System.IO 」这个命名空间,并且引用它的「 File 」,「 File 」之下有好几个方法,如表 7-3 所示,可以协助程序设计师开发档案管理的程序。
 
7-3 档案管理的重要方法(部分列举)
方法
说明
用法
( 假设 EX7-6 完成,
string a= “c://binary.txt”
string b=“c://backup.txt” )
 
Copy
复制现有的档案到新的档案。
File.Copy(a,b,true);// 允许覆写
File.Copy(a,b,false);// 不允许覆写
Delete
删除指定的档案。例外状况不会被掷回,如果指定档案不存在的话。
File.Delete(b);
Exists
判断指定的档案是否存在。档案存在会传回 true ,否则传回 false
Console.WriteLine(File.Exists(a));// 传回 true
GetAttributes
取得路径上档案的 FileAttributes ,如表 7-4 所示。
Console.WriteLine(File.GetAttributes(a));
GetCreationTime
传回指定档案或目录的建立日期和时间。
DateTime t= File.GetCreationTime(a);
GetLastAccessTime
传回指定档案或目录上次被存取的日期和时间。
DateTime t= File.GetLastAccessTime(b);
GetLastWriteTime
传回指定档案或目录上次被写入的日期和时间。
DateTime t= File.GetLastWriteTime(b);
Move
移动指定的档案至新的位置,提供指定新文件名的选项,但是新文件名若已存在会有错误讯息。
File.Delete(b);// 新档名已存在,先删除
File.Move(a,b);// a 更名为 b
Console.WriteLine(File.Exists(aa));// 传回 false ,因为 a 已被重新命名为 b
SetAttributes
在指定路径上设定档案的指定 FileAttributes
File.SetAttributes(a,FileAttributes.ReadOnly);
SetCreationTime
设定档案建立的日期和时间。
DateTime newtime = new DateTime(2005,10,25);
File.SetCreationTime(a,newtime);
SetLastAccessTime
设定指定档案上一次被存取的日期和时间。
DateTime newtime = new DateTime(2005,10,25);
File.SetLastAccessTime(a,newtime);
SetLastWriteTime
设定指定档案上次被写入的日期和时间。
DateTime newtime = new DateTime(2005,10,25); File.SetLastWriteTime(a,newtime);
EX7-06 检查 EX7-05 产生的 c:/binary.txt 是否存在,若存在,为它制作一个备份名叫 c:/backup.txt ,并确实检查 c:/backup.txt 是否存在,再将 c:/binary.txt 删除,然后将 c:/backup.txt 重新命名为 c:/binary.txt ,并检查 c:/binary.txt c:/backup.txt 存在的状况。
 
【解】
if(File.Exists(a))
{
       Console.WriteLine(" 档案 {0}  存在的状况为 {1}", a,File.Exists(a));
       Console.WriteLine(" 以下为档案 {0}  制作一个备份文件 {1}", a,b);
       File.Copy(a,b,true);
       Console.WriteLine(" 接下来删除档案 "+a);
       File.Delete(a);
       Console.WriteLine(" 接下来将档案 {0} 更名为 {1}", b,a);
       File.Move(b,a);
       Console.WriteLine(" 档案 {0} 存在的状况为 {1}", a,File.Exists(a));
       Console.WriteLine(" 档案 {0} 存在的状况为 {1}", b,File.Exists(b));
}      
执行画面如下:
 
 
 

7-4 档案属性 (FileAttributes) 列举
成员名称
说明
FileAttributes. Archive
档案的保存 (Archive) 状态。应用程序使用这个属性标记档案来进行备份或移除。
32
FileAttributes. Compressed
档案是压缩过的。
2048
FileAttributes. Device
保留供将来使用。
64
FileAttributes. Directory
档案是一个目录。
16
FileAttributes. Encrypted
档案或目录是加密过的。对档案而言,这表示档案中的所有数据都被加密。对于目录而言,这表示加密 (Encryption) 是新建档案和目录的默认值。
16384
FileAttributes. Hidden
档案是隐藏的,因此不会包括在一般目录的清单内。
2
FileAttributes. Normal
档案是正常的,并且没有其它属性设定。这个属性只有在单独使用时是有效的。
128
FileAttributes. NotContentIndexed
档案不会由操作系统的内容索引服务进行索引。
8192
FileAttributes. Offline
离线档案。档案数据不是直接可供使用的。
4096
FileAttributes. ReadOnly
档案是只读的。
1
FileAttributes. ReparsePoint
档案包含重新剖析的位置,它是与档案或目录有关联的使用者定义的区块。
1024
FileAttributes. SparseFile
档案是疏松档案。疏松档案基本上为其数据几乎为零值的大型档案。
512
FileAttributes. System
档案是系统档案。档案为操作系统的一部份,或为操作系统所专用。
4
FileAttributes. Temporary
临时文件。当不再需要时,暂存盘应该由应用程序删除。
256
 


 


[1] [1] 另有Read()方法,但本书不介绍
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值