2015-11-12 3 views
3

Мне нужно создать StreamWriter из объекта FileStream и добавить текст в файл . Предполагается, что объект FileStream, который используется, был создан с помощью FileMode.OpenOrCreate и FileAccess.ReadWrite. У меня есть:C# перейти к концу файла с помощью StreamWriter, созданного из FileStream

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

Однако это просто перезаписывает файл с самого начала. Как перейти в конец файла? Есть ли способ изменить FileMode на Append и FileAccess на запись после создания FileStream?

Редактировать: Как уже упоминалось выше, мне нужно сделать это, используя объект 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 уже создан.

+0

Не то же самое. Мне нужно сделать это из существующего объекта FileStream. – EJS

+7

Попробуйте 'fs.Seek (0, SeekOrigin.End)' перед 'sw.WriteLine'. –

+2

В дополнение к тому, что сказал @MarkShevchenko, 'Seek' * before * вы создаете' StreamWriter'. Поиск базового потока - это недокументированное поведение, и оно может сломаться в будущем, независимо от того, что он работает на данный момент. –

ответ

6

Если я правильно понял, вы хотите добавить свою линию в созданный файл:

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

Update:

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

Параметр 'bool append' недоступен при создании StreamWriter из FileStream. Что касается GetCurrentStream(), это часть цикла, который находит имена файлов для файлов, которые необходимо модифицировать на основе алгоритма, а затем выполняет попытку в цикле для блокировки файла, как только он будет доступен, поскольку будет несколько процессов пытаясь получить доступ к файлам. Кроме того, операция добавления к файлу не всегда выполняется, в других случаях чтение файла или чтение и запись необходимы. Возврат объекта FileStream оставляет больше возможностей для выполнения. – EJS

+0

@ EJS больше код, пожалуйста. Показать GetCurrentFileStream(). – StepUp

+0

Добавлена ​​усеченная версия GetCurrentFileStream(). Я думаю, что интересная часть будет частью, где параметры FileStream установлены на '(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)'. – EJS

0

Если вы действительно хотите, вы могли бы довольно это вверх .. ..

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 
     } 
    } 
Смежные вопросы