思路:
文本文件不能随意穿插信息,但是通过使用Seek()方法,可以在读取文本文件中移动光标从而修改所要修改的行.
思路步骤:
1、读取文件,打开csv文件,获取文件流,seek移动光标到开始, for循环寻找出字符“\r\n”,运用两个变量锁定要修改的行数
2、第二个变量锁定后,将后面不修改部分保存到缓存区
2、移动到锁定的位置重写改行数据——实现修改该行的目标,然后重新写入缓存区的不变内容。
下面提供覆盖式修改csv文件的示例代码:
/// <summary> /// 在csv文件某行中覆盖重写 /// </summary> /// <param name="strFilePath">文件路径</param> /// <param name="rowNumber">修改的行数(不包含0)</param> /// <param name="str">覆盖的内容</param> /// <returns></returns> public static bool csv_rowWrite(string strFilePath, int rowNumber, string str) { try { if (!File.Exists(strFilePath)) { MessageBox.Show("读取的文件不存在!!"); return false; } else if (rowNumber <= 0) { MessageBox.Show("该方法不能修改第" + rowNumber + "行"); return false; } using (FileStream fs = new FileStream(strFilePath, FileMode.Open)) { fs.Seek(0, SeekOrigin.Begin); //查找2个换行符位置 //p1定位<修改行的前一个换行符>后一个字节,p2定位<修改行的后一个换行符>后一个字节,用于定位后面的内容缓存到一个缓冲区 long p1 = -1, p2 = -1; var last = 0; //记录换行符个数 int rowNum = 0; for (int i = 0; i < fs.Length; ++i) { if (rowNumber == 1) { p1 = 0; var c = fs.ReadByte(); if (last == '\r' && c == '\n') { p2 = fs.Position; break; } last = c; } else { var c = fs.ReadByte(); if (last == '\r' && c == '\n') { rowNum++; if (rowNum == rowNumber - 1 || rowNum == rowNumber) { if (p1 == -1) { p1 = fs.Position; } else { p2 = fs.Position; break; } } } last = c; } } //未找到行 if (p1 == -1) { MessageBox.Show("路径文件" + strFilePath + "中,第" + rowNumber + "行不存在数据"); return false; } //第二个换行符之后的内容,如果是超大文件,分批缓存,避免内存占用过多 var sr = new StreamReader(fs); //流的当前位置是p2,保存后半部分不修改的内容到缓存区end var end = sr.ReadToEnd(); //重新写入第一个标记点之后的内容 fs.Seek(p1, SeekOrigin.Begin); fs.SetLength(p1); var sw = new StreamWriter(fs); sw.WriteLine(str); sw.Write(end); sw.Flush(); return true; } } catch (Exception ex) { MessageBox.Show("异常:\n" + ex.Message); return false; } }
灵活运用光标位置p1,p2可以实现追加内容的效果。