簡體   English   中英

C# 使用從 FileStream 創建的 StreamWriter 覆蓋文件

[英]C# Overwriting file with StreamWriter created from FileStream

我需要操作文件的內容:

 FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);               
 StreamReader sr = new StreamReader(fs);
 StreamWriter sw = new StreamWriter(fs);
 newString = someStringTransformation(sr.ReadToEnd());
 sw.Write(newString);
 fs.flush();
 fs.Close();

但是,上面附加了 newString 而不是用新更改覆蓋文件。 它需要完成,以便沒有其他應用程序可以在讀取寫入之間訪問該文件,這就是我從 FileStream object 創建讀取器和寫入器的原因。

我知道您可以創建一個將第二個參數設置為 false 的 StreanWriter,如此所述。 但是,當如上所述創建 StreamWriter 時,它似乎不是參數之一。

您遇到的問題是從流中讀取會提前到文件末尾。 然后將追加進一步的寫入。

這將實現完全覆蓋。

using(FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
{
    StreamReader sr = new StreamReader(fs);
    using (StreamWriter sw = new StreamWriter(fs))
    {
        newString = someStringTransformation(sr.ReadToEnd());

        // discard the contents of the file by setting the length to 0
        fs.SetLength(0); 

        // write the new content
        sw.Write(newString);
    }
}

為什么使用SetLength 您的新內容可能比現有字符串短! 您最不想要的是文件末尾的舊內容。

您需要在這里采取幾個步驟,但讓我明確我的假設:

您需要在整個操作過程中保持文件打開和鎖定,以防止其他人在此期間訪問該文件。

話雖如此,這是您需要做的:

  1. 您需要使用StreamReader閱讀內容,就像您所做的那樣
  2. 您需要將底層流重新定位回開始,它的位置已通過閱讀閱讀器而改變
  3. 您需要通過StreamWriter寫出轉換后的內容,就像您所做的那樣
  4. 由於下一步,您需要刷新寫入器
  5. 您需要將底層流/文件截斷到其當前位置,以處理縮短內容的轉換。

所有這些的代碼看起來像這個LINQPad程序:

void Main()
{
    const string filePath = @"d:\temp\test.txt";
    var encoding = Encoding.UTF8;
    using (var stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
    using (var reader = new StreamReader(stream, encoding))
    using (var writer = new StreamWriter(stream, encoding))
    {
        // Read
        var contents = reader.ReadToEnd();

        // Transform
        var transformedContents = contents.Substring(0, Math.Max(0, contents.Length - 1));

        // Write out transformed contents from the start of the file
        stream.Position = 0;
        writer.Write(transformedContents);
        writer.Flush();

        // Truncate
        stream.SetLength(stream.Position);
    }
}

只需使用:

FileStream fs = System.IO.File.Create(filePath);

File.Create 將創建或覆蓋文件並返回文件流。

您可以使用Linq避免這些低級Stream及其Reader / Writer

  File.WriteAllText(filePath, someStringTransformation(File.ReadAllText(filePath)));

您可以做的是重新定位流並刪除緩沖數據以確保沒有任何障礙。 以你的例子為例:

FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);               
 StreamReader sr = new StreamReader(fs);
 StreamWriter sw = new StreamWriter(fs);
 newString = someStringTransformation(sr.ReadToEnd());

    sr.Position = 0;
    sr.DiscardBufferedData(); 

    sw.Position = 0;

 sw.Write(newString);
 fs.flush();
 fs.Close();

如果新數據小於舊數據,則需要截斷剩余數據。 通過使用sw.SetLength(newString.Length); .

也許它會幫助一個。

只需使用FileMode.OpenFileMode.Truncate覆蓋文件:

namespace System.IO
{
    //
    // Summary:
    //     Specifies how the operating system should open a file.
    [ComVisible(true)]
    public enum FileMode
    {
        ...
        //
        // Summary:
        //     Specifies that the operating system should create a new file. If the file already
        //     exists, it will be overwritten. This requires System.Security.Permissions.FileIOPermissionAccess.Write
        //     permission. FileMode.Create is equivalent to requesting that if the file does
        //     not exist, use System.IO.FileMode.CreateNew; otherwise, use System.IO.FileMode.Truncate.
        //     If the file already exists but is a hidden file, an System.UnauthorizedAccessException
        //     exception is thrown.
        Create = 2,
        //
        ...
    }

或者

namespace System.IO
{
    //
    // Summary:
    //     Specifies how the operating system should open a file.
    [ComVisible(true)]
    public enum FileMode
    {
        ...
        //
        // Summary:
        //     Specifies that the operating system should open an existing file. When the file
        //     is opened, it should be truncated so that its size is zero bytes. This requires
        //     System.Security.Permissions.FileIOPermissionAccess.Write permission. Attempts
        //     to read from a file opened with FileMode.Truncate cause an System.ArgumentException
        //     exception.
        Truncate = 5,
        ...
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM