如何有效的使用C#读取文件

 如何有效的使用C#读取文件 <script language="javascript" type="text/javascript">document.title="如何有效的使用C#读取文件 - "+document.title</script>

你平时是怎么读取文件的?使用流读取。是的没错,C#给我们提供了非常强大的类库(又一次吹捧了.NET一番),里面封装了几乎所有我们可以想到的和我们没有想到的类,流是读取文件的一般手段,那么你真的会用它读取文件中的数据了么?真的能读完全么?

通常我们读取一个文件使用如下的步骤:

1、声明并使用FileOpenRead实例化一个文件流对象,就像下面这样

       FileStream fs = File.OpenRead(filename);

或者

       FileStream fs = FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);

2、准备一个存放文件内容的字节数组,fs.Length将得到文件的实际大小,就像下面这样

       byte[] data = new byte[fs.Length];

3、哇!开始读了,调用一个文件流的一个方法读取数据到data数组中

       fs.Read (data, 0, data.Length);

呵呵!我们只写了3句就可以把文件里面的内容原封不动的读出来,真是太简洁了!可以这段代码真的能像你预期的那样工作么?答案是:几乎可以!在大部分情况下上面的代码工作的很好,但是我们应该注意Read方法是有返回值的,既然有返回值那么一定有其道理,如果按照上面的写法完全可以是一个没有返回值的函数。我想返回值的目的是,为了给我们一个机会判断实际读取文件的大小,从而来判断文件是否已经完全读完。所以上面的代码不能保证我们一定读完了文件里面的所有字节(虽然在很多情况下是读完了)。下面的方法提供了一个比上面方法更安全的方法,来保证文件被完全读出

public static void SafeRead (Stream stream, byte[] data){

    int offset=0;

    int remaining = data.Length;

       // 只要有剩余的字节就不停的读

    while (remaining > 0){

        int read = stream.Read(data, offset, remaining);

        if (read <= 0)

            throw new EndOfStreamException("文件读取到"+read.ToString()+"失败!");

              // 减少剩余的字节数

        remaining -= read;

              // 增加偏移量

        offset += read;

    }

}

 

有些情况下你不知道流实际的长度比如:网络流。此时可以使用类似的方法读取流直到流里面的数据完全读取出来为止。我们可以先初始化一段缓存,再将流读出来的流信息写到内存流里面,就像下面这样:

public static byte[] ReadFully (Stream stream){

       // 初始化一个32k的缓存

    byte[] buffer = new byte[32768];

    using (MemoryStream ms = new MemoryStream()){ //返回结果后会自动回收调用该对象的Dispose方法释放内存

              // 不停的读取

        while (true){

            int read = stream.Read (buffer, 0, buffer.Length);

                     // 直到读取完最后的3M数据就可以返回结果了

            if (read <= 0)

                return ms.ToArray();

            ms.Write (buffer, 0, read);

        }

    }

}

 

虽然上面的例子都比较简单,效果也不是很明显(大部分都是对的),也许你早就会了,没关系这篇文章本来就是写给初学者的。

下面的方法提供了一种使用指定缓存长度的方式读取流,虽然在很多情况下你可以直接使用Stream.Length得到流的长度,但是不是所有的流都可以得到。

public static byte[] Read2Buffer (Stream stream, int BufferLen){

       // 如果指定的无效长度的缓冲区,则指定一个默认的长度作为缓存大小

       if (BufferLen < 1){

              BufferLen = 0x8000;

       }

       // 初始化一个缓存区

       byte[] buffer = new byte[BufferLen];

       int read=0;  

       int block;

       // 每次从流中读取缓存大小的数据,知道读取完所有的流为止

       while ( (block = stream.Read(buffer, read, buffer.Length-read)) > 0){

              // 重新设定读取位置

              read += block;

     

              // 检查是否到达了缓存的边界,检查是否还有可以读取的信息

              if (read == buffer.Length){

                     // 尝试读取一个字节

                     int nextByte = stream.ReadByte();

         

                     // 读取失败则说明读取完成可以返回结果

                     if (nextByte==-1){

                            return buffer;

                     }

         

                     // 调整数组大小准备继续读取

                     byte[] newBuf = new byte[buffer.Length*2];

                     Array.Copy(buffer, newBuf, buffer.Length);

                     newBuf[read]=(byte)nextByte;

                     buffer = newBuf;// buffer是一个引用(指针),这里意在重新设定buffer指针指向一个更大的内存

                     read++;

              }

       }

       // 如果缓存太大则使用ret来收缩前面while读取的buffer,然后直接返回

       byte[] ret = new byte[read];

       Array.Copy(buffer, ret, read);

       return ret;

}

using System;
using System.IO;
using System.Collections;

namespace TextFileReader_csharp
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
static void Main(string[] args)
{
StreamReader objReader = new StreamReader("c://test.txt");
string sLine="";
ArrayList arrText = new ArrayList();

while (sLine != null)
{
sLine = objReader.ReadLine();
if (sLine != null)
arrText.Add(sLine);
}
                        objReader.Close();

foreach (string sOutput in arrText)
Console.WriteLine(sOutput);
Console.ReadLine();
}
}
}
 
展开阅读全文

如何有效使用ADODB.RecordSet?

01-28

我们都知道ADODB。RecordSet有以下两种写法rndim recTemp as adodb.recordesetrnset recTemp = new adodb.recoordsetrn与rndim recTemp as new adodb.recordestrnrn'为此,我做了如下的测试程序rnrnOption ExplicitrnrnPrivate AdoRs1 As ADODB.RecordsetrnPrivate AdoRs2 As New ADODB.RecordsetrnrnPrivate Sub CmdTest_Click()rn 'Step1: 新建一个ADODB.RecordSet实例; 注意 AdoRs2不需要新建rn rn Set AdoRs1 = New ADODB.Recordsetrn rn 'Step2: 执行某些操作rn MsgBox "AdoRs1字段个数 :" & AdoRs1.Fields.Countrn MsgBox "AdoRs2字段个数 :" & AdoRs2.Fields.Countrn rn 'Step3: 释放RecordSetrn If AdoRs1.State = adStateOpen Thenrn AdoRs1.Closern End Ifrn Set AdoRs1 = Nothingrn rn If AdoRs2.State = adStateOpen Thenrn AdoRs2.Closern End Ifrn Set AdoRs2 = Nothingrn rn 'Step4: 测试被释放后的RecordSet (注意测试的顺序)rn If AdoRs1 Is Nothing Thenrn MsgBox "AdoRs1 被完全释放 !"rn Elsern MsgBox "AdoRs1 没有被完全释放 !"rn End Ifrn rn If AdoRs2 Is Nothing Thenrn MsgBox "AdoRs2 被完全释放 !"rn Elsern MsgBox "AdoRs2 没有被完全释放 !"rn End Ifrn rn MsgBox "AdoRs2字段个数 :" & AdoRs2.Fields.Countrn MsgBox "AdoRs1字段个数 :" & AdoRs1.Fields.Countrn rnEnd Subrnrn'经过以上测试后, 我们发现一个有趣的现象:rn 'AdoRs1被释放后不能读取AdoRs1的某些属性 , 必须重新执行rn 'Set AdoRs1 = New ADODB.Recordset 方可使用某些属性rn '这样可能造成某些不方便rn rn 'AdoRs2被释放后仍然能读取AdoRs2的某些属性rn '这样是否会造成资源没有被完全释放,造成对程序运行效率的影响rn rn '希望大家能对该问题进行一些讨论和指教,谢谢。rnrn 论坛

c#读取文件乱码

07-06

excel2007 c#读取的时候 乱码 rnrn /// rn /// 取得一个文本文件的编码方式。rn /// rn /// 文件名。rn /// 默认编码方式。当该方法无法从文件的头部取得有效的前导符时,将返回该编码方式。rn /// rn public static Encoding GetEncoding(string fileName, Encoding defaultEncoding)rn rn FileStream fs = new FileStream(fileName, FileMode.Open);rn Encoding targetEncoding = GetEncoding(fs, defaultEncoding);rn fs.Close();rn return targetEncoding;rn rn /// rn /// 取得一个文本文件流的编码方式。rn /// rn /// 文本文件流。rn /// 默认编码方式。当该方法无法从文件的头部取得有效的前导符时,将返回该编码方式。rn /// rn public static Encoding GetEncoding(FileStream stream, Encoding defaultEncoding)rn rn Encoding targetEncoding = defaultEncoding;rn if (stream != null && stream.Length >= 2)rn rn //保存文件流的前4个字节rn byte byte1 = 0;rn byte byte2 = 0;rn byte byte3 = 0;rn byte byte4 = 0;rn //保存当前Seek位置rn long origPos = stream.Seek(0, SeekOrigin.Begin);rn stream.Seek(0, SeekOrigin.Begin);rnrn int nByte = stream.ReadByte();rn byte1 = Convert.ToByte(nByte);rn byte2 = Convert.ToByte(stream.ReadByte());rn if (stream.Length >= 3)rn rn byte3 = Convert.ToByte(stream.ReadByte());rn rn if (stream.Length >= 4)rn rn byte4 = Convert.ToByte(stream.ReadByte());rn rn //根据文件流的前4个字节判断Encodingrn //Unicode 0xFF, 0xFE;rn //BE-Unicode 0xFE, 0xFF;rn //UTF8 = 0xEF, 0xBB, 0xBF;rn if (byte1 == 0xFE && byte2 == 0xFF)//UnicodeBern rn targetEncoding = Encoding.BigEndianUnicode;rn rn if (byte1 == 0xFF && byte2 == 0xFE && byte3 != 0xFF)//Unicodern rn targetEncoding = Encoding.Unicode;rn rn if (byte1 == 0xEF && byte2 == 0xBB && byte3 == 0xBF)//UTF8rn rn targetEncoding = Encoding.UTF8;rn rn //恢复Seek位置 rn stream.Seek(origPos, SeekOrigin.Begin);rn rn return targetEncoding;rn rnrnrn StreamReader sr = new StreamReader(FileUd.PostedFile.InputStream, Helper.GetEncoding(fileName,Encoding.Default));//用该编码创建StreamReader 论坛

关于C#读取文件

01-14

各位大虾求救啊rn rnC#里先读取XML再浏览其他文件可以但是浏览文件之后再读XML就自动结束程序rn只是什么问题呀?rnrn浏览代码rn System.Windows.Forms.OpenFileDialog openFileDialog1 = new System.Windows.Forms.OpenFileDialog();rn private void search_Click(object sender, EventArgs e)rn rn this.openFileDialog1.Filter = "txt文件(*.txt)|*.txt|word文件(*.doc)|*.doc";rnrn if (this.openFileDialog1.ShowDialog() == DialogResult.OK)rn rn this.bookpath.Text = this.openFileDialog1.FileName;rnrn rn rnrn读取XML文件代码rn private void booktype_DropDown(object sender, EventArgs e)rn rn string[] type;rn type = new string[255];rn type = XmlOperation.TraversalXmlFileRetrueGroup("xmlBookinfo.xml", "types", "booktype");rn for (int i = 0; i < type.Length; i++)rn rn if (type[i] != null)rn booktype.Items.Add(type[i]);rn elsern break;rn rn booktype.Text = type[0];rn rnXML代码rn public static string[] TraversalXmlFileRetrueGroup(string filePath, string parentNodeName, string getNodeName) //不带搜索条件的遍历rn rn string[] reXmlValue;rn //最多同时返回255个值rn reXmlValue = new string[PublicConnStr.xmlOutputMaxNum];rn int reNum = 0;rn //初始化XML文档操作类rn XmlDocument myDoc = new XmlDocument();rn //加载XML文件rn myDoc.Load(filePath);rn //搜索指定的节点rn System.Xml.XmlNodeList nodes = myDoc.SelectNodes("//" + parentNodeName);rnrn if (nodes != null)rn rn foreach (System.Xml.XmlNode xn in nodes)rn rn reXmlValue[reNum] = xn.SelectSingleNode(getNodeName).InnerText.Trim();rn reNum++;rn rnrn rn return reXmlValue;rn 论坛

没有更多推荐了,返回首页