理论上,可以使用FileStream类读取和显示文本文件。前面已经介绍了这个类。上面显示NewFile.txt文件的格式不太容易理解,但这并不是FileStream类的问题——而在于我们在文本框中显示结果所使用的方式。
如果知道某个文件包含文本,通常就可以使用StreamReader 和 StreamWriter类更方便地读写它们。这是因为这些类工作的级别比较高,特别适合于读写文本。它们执行的方法可以根据流的内容,自动检测出停止读取文本较方便的位置,特别是:
●这些类执行的方法可以一次读写一行文本(StreamReader.ReadLine() 和 StreamWriter.WriteLine())。在读取文件时,流会自动确定下一个回车符的位置,并在该处停止读取。在写入文件时,流会自动把回车符和换行符添加到文本的末尾。
●使用StreamReader 和 StreamWriter类,就不需要担心文件中使用的编码方式(文本格式)了。可能的编码方式是ASCII(一个字节表示一个字符)或者基于Unicode的格式,UNICODE、UTF7和 UTF8。Windows 9x系统上的文本文件总是ASCII格式,因为Windows 9x系统不支持Unicode,但Windows NT、2000、XP和2003都支持Unicode,所以文本文件除了包含ASCII数据之外,理论上可以包含Unicode、UTF7或 UTF8数据。其约定是:如果文件是ASCII格式,就只包含文本。如果是Unicode格式,就用文件的前两个或三个字节来表示,这几个字节可以设置为表示文件中格式的值的特定组合。
这些字节称为字节码标记。在使用标准Windows应用程序打开一个文件时,例如Notepad 或 WordPad,不需要考虑这个问题,因为这些应用程序都支持不同的编码方法,会自动正确地读取文件。StreamReader类也是这样,它可以正确读取任何格式的文件,而StreamWriter类可以使用任何一种编码技术格式化它要写入的文本。另一方面,如果要使用FileStream类读取和显示文本文件,就不必自己处理这个过程了。
图 30-9
首先看看SaveFile(),因为它是最简单的一个函数。首先利用StreamReader.WriteLine()方法把文本框中的每行文本依次写入StreamWriter流,并在每行文本的最后加上回车换行符:
void SaveFile()
{
StreamWriter sw = new StreamWriter(chosenFile, false,
Encoding.Unicode);
foreach (string line in textBoxContents.Lines)
sw.WriteLine(line);
sw.Close();
}
chosenFile是主窗体的一个字符串字段,它包含已经读取的文件的名称(与前面的示例一样)。注意在打开流时指定Unicode编码方式。如果要以其他格式写入文件,则只需要改变该参数的值。如果要把文本追加到文件中,这个构造函数的第二个参数就设置为true,但本例不是这样。在构造时必须为StreamWriter设置编码方式,可以使用只读属性Encoding。
下面介绍文件的读取方式。读取过程比较复杂,因为我们不知道要读取的文件中包含多少行文本(换言之,文件中包含多少个(char)13 – (char)10序列,因为char(13) –char(10)是行末的回车换行符)。解决这个问题的方式是,先把文件读入一个StringCollection类的实例,该类在System.Collections.Specialized命名空间中,主要用于保存可动态扩展的一组字符串。它的两个方法是我们感兴趣的:把字符串添加到集合中的Add()和把字符串集合复制到一个数组(一个System.Array实例)中的CopyTo()。StringCollection对象的每个元素包含文件中的一行文本。
DisplayFile()方法调用另一个方法ReadFileIntoStringCollection(),来读取文件。之后,就知道文件中有多少行文本了。把StringCollection复制到大小固定的数组中,并把数组中的内容填充到文本框中。在进行复制时,只复制了字符串的引用,没有复制字符串本身,所以该过程的执行效率很高:
void DisplayFile()
{
StringCollection linesCollection = ReadFileIntoStringCollection();
string [] linesArray = new string[linesCollection.Count];
linesCollection.CopyTo(linesArray, 0);
this.textBoxContents.Lines = linesArray;
}
StringCollection.CopyTo()的第二个参数表示目标数组中的下标,我们从该下标指定的位置开始复制集合。
下面看看ReadFileIntoStringCollection()方法。使用StreamReader读取每一行文本。编译时需要计算读取的字符数,以确保不超出文本框的范围:
StringCollection ReadFileIntoStringCollection()
{
const int MaxBytes = 65536;
StreamReader sr = new StreamReader(chosenFile);
StringCollection result = new StringCollection();
int nBytesRead = 0;
string nextLine;
while ( (nextLine = sr.ReadLine()) != null)
{
nBytesRead += nextLine.Length;
if (nBytesRead > MaxBytes)
break;
result.Add(nextLine);
}
sr.Close();
return result;
}
这就是该示例的完整代码。
如果运行ReadWriteText,读取NewFile.aspx文件,然后保存它,该文件的格式就是Unicode。任何常用的Windows应用程序(Notepand,Wordpad)都没有提供这种格式,甚至ReadWriteText示例也只能在Windows NT/2000/XP/2003下正确读取和显示文件。因为Windows 9x不支持Unicode,像Notepad这样的应用程序不能识别其他平台上的Unicode文件(如果从Wrox Press网站上下载了这个示例,就可以试试)。但是,如果使用前面的ReadBinaryFile示例显示文件,就会立即看出它们的区别,如图30-10所示。最前面的两个字节表示文件的格式是Unicode,之后,每个字符都用两个字节来表示。这是非常明显的,因为在这个文件中,每个字符的高位字节都是0,所以每隔一个字节就显示x00。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。