C#使用由FileStream创建的StreamWriter将指针移动到文件末尾

5

我需要从一个FileStream对象创建一个StreamWriter,并向文件中追加一些文本。假设正在使用的FileStream对象已经使用FileMode.OpenOrCreate和FileAccess.ReadWrite创建。我的代码如下:

using (FileStream fs = GetCurrentFileStream())
{
    StreamWriter sw = new StreamWriter(fs);
    sw.WriteLine("StringToAppend");
    sw.Flush();
}

然而,这只是从文件开头覆盖文件。我如何移动到文件末尾?也许有一种方法可以在创建FileStream之后将FileMode更改为Append并将FileAccess更改为Write?编辑:如上所述,我需要使用FileStream对象来完成此操作。打开现有文件,追加单行的答案假定我可以从文件路径创建新的StreamWriter,但我没有。编辑2:添加了GetCurrentFileStream()的截断版本。
    public static FileStream GetCurrentFileStream()
    {
        String fileName = getFileName();
        FileStream fs = OpenFileWhenAvailable(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
    }

    public static FileStream OpenFileWhenAvailable(String fileName, FileMode fileMode, FileAccess fileAccess, FileShare fileShare)
    {
        int tries = 0;
        int timeout = 10 * 1000;
        while (true)
        {
            tries++;
            try
            {
                return new FileStream(fileName, fileMode, fileAccess, fileShare);
            }
            catch (IOException ex)
            {
                if (tries * 100 > timeout)
                {
                    return null;
                }
                else
                {
                    System.Threading.Thread.Sleep(100);
                }
            }
        }
    }

GetCurrentFileStream在多种不同的情境下使用,因此直接更改FileMode和FileAccess不是一个选项。我不想为这个特殊情况创建一个单独的GetCurrentFileStream版本,这就是为什么我在问是否有一种方法可以在FileStream对象已经被创建时跳到流的末尾并追加一个字符串。


不一样。我需要从现有的FileStream对象中进行操作。 - EJS
11
sw.WriteLine 之前尝试使用 fs.Seek(0, SeekOrigin.End) - Mark Shevchenko
2
除了@MarkShevchenko所说的之外,在创建StreamWriter之前,应该先进行Seek操作。寻找基础流是未记录的行为,它可能会在将来出现问题,无论它目前是否正常工作。 - Jonathan Dickinson
2个回答

9

如果我理解正确,您想将您的行附加到一个已经创建的文件中:

using (FileStream fs = GetCurrentFileStream())
{
    StreamWriter sw = new StreamWriter(fs, true);
    sw.WriteLine("StringToAppend");
    sw.Flush();
}

通过使用StreamWriter构造函数的重载,您可以选择是追加文件还是覆盖文件。
如果您能展示一下GetCurrentStream()方法的实现,那就太棒了。
using (FileStream fileStream = new FileStream(fileName,FileMode.Append, FileAccess.Write))
using (StreamWriter sw = new StreamWriter(fs))
{
   sw.WriteLine(something);
}

更新:

using (FileStream fs = GetCurrentFileStream())
{
   StreamWriter sw = new StreamWriter(fs);
   long endPoint=fs.Length;
   // Set the stream position to the end of the file.        
   fs.Seek(endPoint, SeekOrigin.Begin);
   sw.WriteLine("StringToAppend");
   sw.Flush();
 }

2
在使用FileStream构造StreamWriter时,参数bool append不可用。至于GetCurrentStream(),它是循环的一部分,根据算法查找需要修改的文件名,然后在循环中尝试锁定文件,因为会有多个进程尝试访问这些文件。此外,追加到文件的操作并不总是会执行,有时需要读取文件或同时进行读写操作。返回一个FileStream对象可以提供更多的选择。 - EJS
@EJS,请再放一些代码。展示GetCurrentFileStream()函数。 - StepUp
添加了GetCurrentFileStream()的截断版本。我认为有趣的部分将是设置FileStream参数为(fileName,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None)的部分。 - EJS
@EJS,尝试像第二个示例中所示一样在构造函数中设置必要的参数。如果您对此有困难,可以告诉我,我会尽力提供帮助。 - StepUp
正如我在编辑中所解释的那样,我不能直接更改参数,因为这会导致该方法在其他情况下失败。我将在问题的顶部添加一个条件来考虑这一点。 - EJS
显示剩余2条评论

-1

如果你真的非常想要,你可以把它弄得漂亮一些...

    static int iMaxLogLength = 15000;
    static int iTrimmedLogLength = -2000;

    static public void writeToFile2(string strMessage, string strLogFileDirectory, int iLogLevel)
    {
        string strFile = strLogFileDirectory + "log.log";

        try
        {
            FileInfo fi = new FileInfo(strFile);

            Byte[] bytesRead = null;

            if (fi.Length > iMaxLogLength)
            {
                using (BinaryReader br = new BinaryReader(File.Open(strFile, FileMode.Open)))
                {
                    // Go to the end of the file and backup some
                    br.BaseStream.Seek(iTrimmedLogLength, SeekOrigin.End);

                    // Read that.
                    bytesRead = br.ReadBytes((-1 * iTrimmedLogLength));
                }
            }

            byte[] newLine = System.Text.ASCIIEncoding.ASCII.GetBytes(Environment.NewLine);

            FileStream fs = null;
            if (fi.Length < iMaxLogLength)
                fs = new FileStream(strFile, FileMode.Append, FileAccess.Write, FileShare.Read);
            else
                fs = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read);

            using (fs)
            {
                if (bytesRead != null)
                {
                    fs.Write(bytesRead, 0, bytesRead.Length);
                    fs.Write(newLine, 0, newLine.Length);
                    Byte[] lineBreak = Encoding.ASCII.GetBytes("### " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " *** *** *** New Log Start Position *** *** *** *** ###");
                    fs.Write(lineBreak, 0, lineBreak.Length);
                    fs.Write(newLine, 0, newLine.Length);
                }
                Byte[] sendBytes = Encoding.ASCII.GetBytes(strMessage);
                fs.Write(sendBytes, 0, sendBytes.Length);
                fs.Write(newLine, 0, newLine.Length);
            }
        }
        catch (Exception ex)
        {
            ; // Write to event or something
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接