对同一个文件进行读写
本文关键字:读写 文件 同一个 | 更新日期: 2023-09-27 18:05:05
我正在经历一个循环,对于每次运行,我希望打开一个txt/csv文件并搜索在循环中分配的值。如果该值存在于txt文件中,我希望在这一行写入它。
这能做到吗?我一直在玩StreamReader和StreamWriter,但从来没有真正成功地读取和写入同一个文件。
我一开始尝试了这个,但显然StreamReader使文件"忙",因此StreamWriter无法访问它。
private void WriteTempTXT()
{
StreamReader sr = new StreamReader(@tmpfile);
StreamWriter sw = new StreamWriter(@tmpfile);
}
有办法做到这一点吗?
首先,这是可以做到的。您可以创建具有读写权限的FileStream
,然后直接写入流。下面是一个概念证明:
using (var v = new StreamWriter(File.Create("a.txt"))) {
v.WriteLine("1234A67890");
}
FileStream fs = new FileStream("a.txt", FileMode.Open, FileAccess.ReadWrite);
while (fs.ReadByte() != 'A') {} // Dangerous. Loops until 'A' found, infinite loop if none.
fs.Position--;
fs.WriteByte((byte)'5');
fs.Close(); // contents of a.txt now 1234567890
然而,这种方法存在一些基本问题:
- 文件损坏风险。如果程序崩溃(或停电等),文件可以保持在不一致的状态
- 无法一致使用
StreamReader
/StreamWriter
。都将数据存储在内部缓冲区中,如果底层流被并发地写入和读取,则该缓冲区可能会失效。您可以调用DiscardBufferedData
,但是MSDN指出"这个方法会降低性能,应该只在绝对必要的时候调用"。 - 的复杂性。在文件中插入文本是一个昂贵的操作,需要将所有后续数据移到内存中。
相反,除非有压倒性的考虑(例如,文件相对于可用存储空间来说太大),您可能想要考虑这种方法:
- 创建新的临时文件。(您可以使用
System.IO.Path.GetTempFileName()
用于此目的)。 - 将现有文件读入临时文件,进行必要的更改。(使用
StreamReader
读取旧文件,使用StreamWriter
写入新文件) - 用临时文件覆盖现有文件
这种方法在概念上是相似的,但不会产生并发地读写同一流的风险和复杂性。
在CSV文件中写入一行有两个问题:
-
文件不是基于行。只有当新行编码的数据与原始行完全相同的字节数时,才能替换文件中的行。
-
CSV数据不是基于行。换行符被用作记录分隔符,但是作为一个值也可以包含换行符,您不能可靠地逐行读取CSV文件(除非在特殊情况下,您确定没有值将包含新行)。
如果新行编码的数据长度与旧行不同,则必须重写文件的其余部分以为添加的字节腾出空间或删除未使用的字节。
通常的方法是读取整个文件并将其解析为记录,更改记录,然后将整个文件写回来。
首先你需要跟进这个示例
然后使用类string path = Server.MapPath("Twitter Overview Report1.csv");
using (CsvFileReader reader = new CsvFileReader(path))
{
CsvRow row = new CsvRow();
while (reader.ReadRow(row))
{
foreach (string s in row)
{
string s_row = row[0].ToString();
s_row.Replace("mahmoude", "Ghandour");
}
Console.WriteLine();
}
}
using (CsvFileWriter writer = new CsvFileWriter(path))
{
}