【问题标题】:C# move to end of file with StreamWriter created from FileStreamC# 使用从 FileStream 创建的 StreamWriter 移动到文件末尾
【发布时间】:2015-11-12 12:29:13
【问题描述】:

我需要从 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 对象来执行此操作。 Open existing file, append a single line 的答案假设我可以从我没有的文件路径创建一个新的 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 对象中执行此操作。
  • sw.WriteLine 之前尝试fs.Seek(0, SeekOrigin.End)
  • 除了@MarkShevchenko 所说的,Seek 你创建StreamWriter 之前。寻找底层流是未记录的行为,它可能会在未来中断,不管它目前是否有效。

标签: c# filestream


【解决方案1】:

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

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();
 }

【讨论】:

  • 从 FileStream 构造 StreamWriter 时,参数bool append 不可用。至于 GetCurrentStream(),它是循环的一部分,它根据算法查找需要修改的文件的文件名,然后在循环中执行尝试以在文件可用时立即锁定文件,因为会有多个进程试图访问文件。此外,附加到文件的操作并不总是会执行,其他时候读取文件或同时进行读取和写入是必要的。返回一个 FileStream 对象为做什么留下了更多的选择。
  • @EJS 更多代码,请。显示 GetCurrentFileStream()。
  • 添加了 GetCurrentFileStream() 的截断版本。我认为有趣的部分将是 FileStream 参数设置为 (fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None) 的部分。
  • @EJS 因此尝试在构造函数中设置必要的参数,如第二个示例所示。如果您对此有任何疑问,请告诉我,我可以尝试进一步提供帮助。
  • 正如我在编辑中解释的那样,我不能直接更改参数,因为这会使该方法在其他上下文中失败。我将在我的问题顶部添加一个条件来考虑这一点。
【解决方案2】:

如果你真的想要,你可以把它美化......

    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
        }
    }

【讨论】:

    猜你喜欢
    • 2016-02-12
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-17
    相关资源
    最近更新 更多