在同一文本文件上使用 StreamReader 和 Writer

Using StreamReader & Writer on same Textfile

我最近 运行 遇到了一个问题,我找不到适合我需要的解决方案。所以我试图逐行读取文本文件并检查该行是否是特定字符串。如果文件不包含该字符串,则应将其写入文件。这是我目前的做法。

int i = 0;
using (var sw = new StreamWriter(this.filePath))
{
    foreach (SimplePlaylist playlist in myPlaylists)
    {
        this.PlaylistTracks[i] = new List<PlaylistTrack>();
        this.PlaylistTracks[i] = GetPlaylistTracks(playlist.Owner.Id, playlist.Id);
        foreach (PlaylistTrack tr in this.PlaylistTracks[i])
        {
            string write = tr.Track.Name + " // " + string.Join(",", tr.Track.Artists.Select(source => source.Name)) + " // " + tr.Track.Album.Id;
            string line = "";
            bool found = false;
            using (var sr = new StreamReader(this.filePath))
            {
                while ((line = sr.ReadLine()) != null)
                {
                    if (line.Equals(write))
                    {
                        found = true;
                        break;
                    }
                }
                sr.Close();
            }
            if (!found)
            {
                sw.WriteLine(write);
            }
        }
        i++;
    }
    sw.Close();
}

我看过关于同时读写文件的问题,但我想知道是否有办法实现这一点。感谢您的帮助!

使用 FileStream 并将其用于 StreamReader 和 StreamWriter,这里是添加或更改文本文件行的示例:

public static void ChangeOrAddLine(string filePath, string newLine, string oldLine = "")
{
    using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read))
    using (StreamReader sr = new StreamReader(fs))
    using (StreamWriter sw = new StreamWriter(fs))
    {
        List<string> lines = sr.ReadToEnd().Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList();
        fs.Position = 0;
        bool lineFound = false;
        if (oldLine != "")
            for (int i = 0; i < lines.Count; i++)
                if (lines[i] == oldLine)
                {
                    lines[i] = newLine;
                    lineFound = true;
                    break;
                }
        if (!lineFound)
            lines.Add(newLine);
        sw.Write(string.Join("\r\n", lines));
        fs.SetLength(fs.Position);
    }
}

FileAccess.ReadWrite打开文件读写

FileShare.Read让其他程序也能读取

请注意,您当前的方法效率很低,需要您的代码从磁盘读取文件以搜索每个字符串。

您将无法像您尝试的那样使用两个不同的流同时读取和写入同一个文件。以下是我在不了解更多情况下建议的一些策略:

  1. 如果文件较小,将while文件载入List,关闭reader。然后您可以在列表中搜索每个字符串:

    if(!list.Any(write))
        // Write the string to the file  
    

    这会非常快,因为列表在内存中并且文件只被读取一次(前提是它相当小 - 比如 < 5000 行,尽管它也适用于更大的文件)。

  2. 另一种方法是将缺失的字符串添加到列表中,一旦您确定了所有缺失的字符串,关闭 reader 并使用编写器添加字符串。这仍然是低效的,因为每次查找都在读取文件(可能很大),所以

  3. 此方法的一个改进是通读文件并根据您可能要添加的所有行检查每一行。这意味着您只需读取文件一次,然后 运行 遍历每一行的播放列表集合,这样效率会更高,因为它在内存中。假设您只有几行要检查 - 比如说您要添加的一些新歌曲,这将提高很多倍的效率。

如果文件变得非常大,您可能需要某种索引查找方法。

另一个不建议的选项是在原始文件上打开 reader,在临时文件上打开一个 writer。从原始文件读取写入临时文件并添加缺少的行,然后用临时文件替换原始文件。