2014-7-25-FileStream StreamReader

本文介绍了在C#中使用FileStream和StreamReader进行文件读写的正确方式,避免因未正确释放资源而导致的IOException。同时,提供了创建文件并立即写入内容的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

经验提醒:读写IO操作一定要加using(){}释放资源,否则会报 IO Exception:文件无法访问,正在由另一进程使用


一、FileStream流创建文件,用FileStream流实例化StreamReader紧接着读取

正常思路(错误的思路)我们会先创建文件,接着读取。如下代码:

//FileInfo先创建 

FileInfo fi = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + filename + ".txt");

            if(!fi.Exists)

            {

                fi.Create();

            }

            string lastline = "";

//StreamReader再读取

            using (StreamReader sr = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + filename + ".txt"))

            {

                while (sr.EndOfStream)

                {

                    lastline = sr.ReadLine();

                }

            }


这样程序会报“xxxxx文件正由另一进程使用...无法读取”的错误。

猜测:使用FileInfo对象创建文件,背后是开启了一个线程创建,StreamReader读取文件也是开启了一个线程读取,由于FileInfo创建文件的对象流无法释放,StreamReader紧接着读取,就报错了。

解决方案如下:采用FileStream流创建文件,用FileStream流实例化一个StreamReader紧接着读取。Code如下:

string fpath = AppDomain.CurrentDomain.BaseDirectory + filename + ".txt";

            if (!File.Exists(fpath))

            {

                FileStream fs = new FileStream(fpath, FileMode.OpenOrCreate, FileAccess.Read);//创建读取文件

                sr = new StreamReader(fs);

                logcontent = sr.ReadToEnd();

                sr.Close();

                fs.Close();

            }




二、创建文件,及时写入

 StreamWriter sw = File.CreateText(versionName);
                sw.WriteLine("1.10.01");
                sw.Close();




<think>我们正在处理一个关于C#StreamReaderFileStream转换的问题。用户想知道如何将StreamReader转换为FileStream或实现类似功能。根据引用资料,我们知道:-FileStream用于操作字节和字节数组,而StreamReader用于操作字符数据(引用[3])。- StreamReader的构造函数可以接受一个FileStream对象(引用[2]),这说明我们可以从FileStream创建StreamReader。但是,用户想要的是反过来:从StreamReader得到FileStream。分析:StreamReader本身是对一个流的包装,这个流可能是FileStream,也可能是其他类型的流(如MemoryStream等)。因此,我们不能直接将StreamReader“转换”为FileStream,因为StreamReader内部可能并不是一个FileStream。然而,我们可以通过以下思路:1.如果StreamReader的底层流是FileStream,那么我们可以尝试获取这个底层流,并判断它是否是FileStream。2.如果底层流是FileStream,那么我们就可以使用它。3.如果底层流不是FileStream(比如是MemoryStream),那么我们就需要将数据写入到一个新的FileStream中,以实现类似的功能。但是,注意:StreamReader类并没有直接提供获取其底层流的方法。不过,我们可以通过反射来获取私有字段,但这样做不安全也不推荐。另一种方法是:如果我们知道StreamReader的底层流是FileStream,并且我们创建这个StreamReader的时候是用FileStream创建的,那么我们可以保留对FileStream的引用,这样就不需要转换了。如果用户确实需要从StreamReader中获取数据并写入到文件,那么我们可以读取StreamReader的内容(比如使用ReadToEnd方法),然后将这些内容写入到一个新的FileStream中。因此,我们可以给出两种方案:方案1:如果我们有创建StreamReader时使用的FileStream的引用,那么直接使用它。方案2:如果没有保留FileStream的引用,那么我们可以将StreamReader的内容读取出来,然后写入到一个新的FileStream中。但是注意:方案2会重新写入整个数据,如果数据量很大,可能会有性能问题。而且,如果原来的StreamReader已经读取了一部分,那么再读取剩余部分写入文件,可能并不是用户想要的。另外,引用[2]中给出了StreamReader读取文件和StreamWriter写入文件的示例代码,我们可以参考。因此,回答应该包括:1.解释为什么不能直接转换。2.提供替代方案。根据以上分析,我们给出回答。</think>### 如何将 StreamReader 转换为 FileStream 或实现类似功能 在 C# 中,`StreamReader` 和 `FileStream` 是两种不同类型的流处理器,无法直接相互转换。但可以通过以下方法实现类似功能: #### 🔧 方法 1:获取底层 FileStream(推荐) 如果 `StreamReader` 是通过 `FileStream` 创建的,可直接获取其底层流: ```csharp StreamReader sr = new StreamReader("file.txt"); if (sr.BaseStream is FileStream fs) // 检查底层流是否为 FileStream { // 现在可直接使用 fs 对象 fs.Seek(0, SeekOrigin.Begin); // 示例:重置文件指针 byte[] buffer = new byte[1024]; int bytesRead = fs.Read(buffer, 0, buffer.Length); } sr.Close(); ``` > 此方法保留了原始文件流的所有特性(如文件指针位置、访问权限等)[^3]。 #### 📥 方法 2:内容复制到新 FileStream 当底层流不是 `FileStream` 时(如网络流),可将内容复制到新文件: ```csharp using (StreamReader sr = new StreamReader(inputStream)) using (FileStream fs = new FileStream("output.txt", FileMode.Create)) { string content = sr.ReadToEnd(); byte[] data = Encoding.UTF8.GetBytes(content); fs.Write(data, 0, data.Length); } ``` #### ⚠️ 关键区别说明 | 特性 | FileStream | StreamReader | |--------------------|---------------------------------|------------------------------| | **数据类型** | 字节级操作 (byte[]) | 字符级操作 (string) | | **典型用途** | 二进制文件/随机访问 | 文本文件/顺序读取 | | **编码处理** | 不处理文本编码 | 自动处理文本编码 | | **构造方式** | 直接操作文件路径 | 包装其他流(如 FileStream) | > 直接转换不可行是因为 `FileStream` 处理原始字节,而 `StreamReader` 处理解码后的字符数据,两者属于不同抽象层级[^3]。 #### 💡 实用建议 1. **设计时保留引用**:创建 `StreamReader` 时同步保存 `FileStream` 引用: ```csharp FileStream fs = new FileStream("data.txt", FileMode.Open); StreamReader sr = new StreamReader(fs); // 后续可直接使用 fs ``` 2. **混合操作场景**: ```csharp using (FileStream fs = new FileStream("file.txt", FileMode.Open)) using (StreamReader sr = new StreamReader(fs)) { string header = sr.ReadLine(); // 文本读取 fs.Seek(0, SeekOrigin.Begin); // 字节级操作 byte[] allData = new byte[fs.Length]; fs.Read(allData, 0, allData.Length); } ``` 3. **编码一致性**:当复制内容时,确保使用与源文件相同的编码: ```csharp Encoding encoding = sr.CurrentEncoding; // 获取原读取器编码 byte[] data = encoding.GetBytes(content); ``` > 最佳实践是在设计时明确需求:需要字节操作直接用 `FileStream`,需要文本解析用 `StreamReader`,两者可协同工作[^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值