在搜索行时覆盖文本文件中的行

时间:2015-02-02 02:20:36

标签: c# streamreader streamwriter

我正在使用C#开发视频游戏。我有一个用户列表,其硬币金额在.txt文件中,我希望他们的金额在保存时被覆盖。我无法弄清楚如何在没有使用"文件的情况下在SteamReader中使用SteamWriter"例外。基本上,我需要搜索用户名,如果找到它,用相同的用户名和新的硬币数量覆盖现有的行。所有硬币金额都在" 0000"格式(0010,0199等),所以我可以使用子串和长度来轻松查找和加载硬币数量。

以下是我尝试使用的代码:

StreamReader sr = new StreamReader("C:\\FakeFilePath");
String line;
try
{
  line = sr.ReadLine();
  while (line != null)
  {
     if (line.Contains(users[m.GetInt(0)].username))
     {
        using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\FakeFilePath", false))
        {
            file.WriteLine("\n" + users[m.GetInt(0)].username + " " + (users[m.GetInt(0)].rupees).ToString("D4"));
            file.Close();
        }
     }
     line = sr.ReadLine();
  }
}
finally
{
    sr.Close();
}

非常感谢任何帮助。

谢谢, dsimathguy

1 个答案:

答案 0 :(得分:0)

你应该通过简单地重写整个文件来做到这一点,正如评论者Jonesy所建议的那样。可能文本文件相对较小,可能比单个磁盘块小(通常为4K大小,但可能因文件系统配置而异),重写整个文件几乎与覆盖一个文件一样快。特定地点。


如果您坚持尝试仅覆盖特定位置,则需要一种可靠的方法来计算文件中要写入的位置,然后在编写之前需要设置StreamWriter.BaseStream对象的位置新数据。您还需要使用读/写访问权限打开文件一次,或者打开一次以进行读取以查找位置,然后将其关闭再打开以进行写入。

计算文件中位置的最简单方法是采用固定大小的字符编码,例如: ASCII或UTF16。使用ASCII,文件中的偏移量(以字节为单位)将与字符数相同;使用UTF16,它将是字符数的两倍。

请注意,每一行也必须有固定的长度;即,您将用户名存储在行中的固定宽度字段中,以及硬币计数。所以该文件可能如下所示:

Username1     0001
User24        0117
SallyDoe999   0037

注意:上面每行有20个字符:名称为14个字符,硬币计数为4个字符,当然还有换行符的两个字符。

例如,假设您将数据存储为ASCII:

string fileName = "C:\\FakeFilePath";

using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite))
using (StreamReader sr = new StreamReader(stream, Encoding.ASCII))
using (StreamWriter writer = new StreamWriter(stream, Encoding.ASCII))
{
    int lineCount = 0;
    String line;

    while ((line = sr.ReadLine()) != null)
    {
        if (line.Contains(users[m.GetInt(0)].username))
        {
            // Offset is the offset of the line itself, plus
            // the length of the name field (the name field doesn't
            // need to be written because it's already the right
            // value!)
            int byteOffset = (lineCount * 20) + 14;

            writer.BaseStream.Position = byteOffset;
            writer.Write(users[m.GetInt(0)].rupees.ToString("D4"));

            break;
        }

        lineCount++;
    }
}

正如您所看到的,这需要付出很多努力,特别是如果您需要更改文件格式的话。有很多挑剔的东西,必须是正确的"那里的代码,它当然会根据文件格式的大小限制你的选择。我希望你能在任何需要改变的时候再次将整个文件写出来,从而看到智慧。 :)