Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 添加带退格的字符串时,从文本文件中删除字符_C#_.net_Text Files_Streamwriter_Backspace - Fatal编程技术网

C# 添加带退格的字符串时,从文本文件中删除字符

C# 添加带退格的字符串时,从文本文件中删除字符,c#,.net,text-files,streamwriter,backspace,C#,.net,Text Files,Streamwriter,Backspace,是否可以将包含backspaces的字符串附加到文本文件中,并将其中的所有backspaces视为“remove last char”操作 例如,我的文本文件: 此文件已被删除 两行 类似这样的C代码: string str = "...\b\b\b\b\b\b\b\b\b\b\b\b\b one line." myFile.Append(str); 执行此代码后,文本文件如下所示: string str = "...\b\b\b\b\b\b\b\b\b\b\b\

是否可以将包含backspaces的字符串附加到文本文件中,并将其中的所有backspaces视为“remove last char”操作

例如,我的文本文件:

此文件已被删除

两行

类似这样的C代码:

string str = "...\b\b\b\b\b\b\b\b\b\b\b\b\b one line."
myFile.Append(str);
执行此代码后,文本文件如下所示:

string str = "...\b\b\b\b\b\b\b\b\b\b\b\b\b one line."
myFile.Append(str);
这个文件只有一行

StreamWriter
File
类似乎没有多大帮助

如果不在每个附加操作中读取和写入整个文件,我就无法找到实现此功能的最佳方法,这可能会导致大型文本文件出现严重的性能问题。其思想是使用此新功能将日志语句集中写入文本文件

第二个问题是如何处理windows样式的新行字符(“\r\n”)?i、 e.一个退格应删除整个换行符序列(“\r\n”)

关于如何实现这一点有什么想法吗

非常感谢您的源代码。

在“最一般情况下”正确地执行它非常非常困难。NET中没有直接的支持。让我们看看最新技术:

  • 有一个
    FileStream
    类。。。它是读/写的。可悲的是,它不知道编码,它以字节为单位工作。因此本机没有UTF-8和Unicode。你看到你漂亮的尼克了吗?它显然需要一些编码:-)

  • StreamReader
    StreamWriter
    可以“连接”到
    FileStream
    。。。遗憾的是,它们是分开的(一个是只读的,一个是写的),遗憾的是它们预缓冲,因此
    FileStream.Position
    StreamReader
    中当前的“read”字符不对应。这使得使用
    StreamReader
    进行读取,然后使用
    StreamWriter
    进行“就地”更正变得相当复杂

  • 即使我们有一个
    StreamReaderWriter
    ,也会有点困难。NET与UTF-16
    char
    s配合使用,因此许多Unicode字符(类似表情符号在“最一般情况下”正确使用)非常非常困难。在.NET中没有直接支持。让我们看看最新技术:

    • 有一个
      FileStream
      类…它是读/写的。遗憾的是,它不知道编码,它是以字节为单位工作的。所以没有UTF-8,也没有Unicode本机。你可以看到你美丽的尼克
      sɐunıɔןqɐp
      ?它显然需要一些编码:-)

    • StreamReader
      StreamWriter
      可以“连接”到
      FileStream
      。。。遗憾的是,它们是分开的(一个是只读的,一个是写的),遗憾的是它们预缓冲,因此
      FileStream.Position
      StreamReader
      中当前的“read”字符不对应。这使得使用
      StreamReader
      进行读取,然后使用
      StreamWriter
      进行“就地”更正变得相当复杂

    • 即使我们有一个
      StreamReaderWriter
      ,也会有点困难。NET与UTF-16
      char
      s一起工作,因此许多Unicode字符(类似于的表情符号)都是基于和基于,我编写了这个原型
      FileLogger
      类,它将字符串(要附加的)计算为初始退格字符序列和剩余字符串(没有任何退格)

      如果存在初始退格,程序将根据初始退格的数量(以非常简单的方式)截断
      FileStream
      对象,然后追加剩余的字符串

      不幸的是,这个解决方案不考虑任何代码> > R\N\/Cord-NeXLINE序列,它应该由一个单一的退格空间移除,既可以从<代码> FielestRAM和附加的字符串中删除。现在,需要两个退格来移除一个Windows样式的新行字符序列。

      using System;
      using System.Collections.Generic;
      using System.Globalization;
      using System.IO;
      using System.Linq;
      using System.Text;
      
      namespace Example
      {
          public static class FileLogger
          {
              public static bool IsStarted { get; private set; }
              public static Encoding Encoding { get; private set; }
              public static string LogFilePath { get; private set; }
      
              private static FileStream FS;
              private static int BytesPerChar;
              private static readonly object Locker = new object();
      
              public static void Start(string logFilePath, Encoding encoding = null)
              {
                  lock (Locker)
                  {
                      if (IsStarted) return;
                      LogFilePath = logFilePath;
                      Encoding = encoding ?? Encoding.UTF8;
                      if (File.Exists(LogFilePath)) File.SetAttributes(LogFilePath, FileAttributes.Normal);
                      FS = new FileStream(LogFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 4096, FileOptions.RandomAccess);
                      FS.SetLength(0);
                      FS.Flush();
                      BytesPerChar = Encoding.UTF8.GetByteCount(new[] { 'A' });
                      IsStarted = true;
                  }
              }
      
              public static void Close()
              {
                  lock (Locker)
                  {
                      if (!IsStarted) return;
                      try { FS?.Close(); } catch { }
                      FS = null;
                      IsStarted = false;
                  }
              }
      
              public static void WriteToFile(string text)
              {
                  lock (Locker)
                  {
                      if (string.IsNullOrEmpty(text)) return;
      
                      if (!text.Contains('\b'))
                      {
                          FS.Position = FS.Length;
                          byte[] bytes = Encoding.GetBytes(text);
                          FS.Write(bytes, 0, bytes.Length);
                          FS.Flush();
                          return;
                      }
      
                      // Evaluates the the string into initial backspaces and remaining text to be appended:
                      EvaluateText(text, out int initialBackspaces, out string remainingText);
      
                      // If there are no initial backspaces after evaluating the string, just append it and return:
                      if (initialBackspaces <= 0)
                      {
                          if (string.IsNullOrEmpty(remainingText)) return;
      
                          FS.Position = FS.Length;
                          byte[] bytes = Encoding.GetBytes(remainingText);
                          FS.Write(bytes, 0, bytes.Length);
                          FS.Flush();
                          return;
                      }
      
                      // First process the initial backspaces:
                      long pos = FS.Length - initialBackspaces * BytesPerChar;
                      FS.Position = pos > 0 ? pos : 0;
                      FS.SetLength(FS.Position);
      
                      // Then write any remaining evaluated text:
                      if (!string.IsNullOrEmpty(remainingText))
                      {
                          byte[] bytes = Encoding.GetBytes(remainingText);
                          FS.Write(bytes, 0, bytes.Length);
                      }
                      FS.Flush();
                      return;
                  }
              }
      
              public static void EvaluateText(string text, out int initialBackspaces, out string remainingTextToAppend)
              {
                  initialBackspaces = 0;
                  StringBuilder sb = new StringBuilder();
                  foreach (char ch in text)
                  {
                      if(ch == '\b')
                      {
                          if (sb.Length > 0) sb.Length--;
                          else initialBackspaces++;
                      }
                      else sb.Append(ch);
                  }
                  remainingTextToAppend = sb.ToString();
              }
          }
      }
      
      输出(test.log文件):

      阿克斯

      基于并基于此,我编写了这个原型
      FileLogger
      类,它将字符串(要追加的)计算为初始退格字符加上剩余字符串(没有任何退格)的序列

      如果存在初始退格,程序将根据初始退格的数量(以非常简单的方式)截断
      FileStream
      对象,然后追加剩余的字符串

      不幸的是,这个解决方案不考虑任何代码> > R\N\/Cord-NeXLINE序列,它应该由一个单一的退格空间移除,既可以从<代码> FielestRAM和附加的字符串中删除。现在,需要两个退格来移除一个Windows样式的新行字符序列。

      using System;
      using System.Collections.Generic;
      using System.Globalization;
      using System.IO;
      using System.Linq;
      using System.Text;
      
      namespace Example
      {
          public static class FileLogger
          {
              public static bool IsStarted { get; private set; }
              public static Encoding Encoding { get; private set; }
              public static string LogFilePath { get; private set; }
      
              private static FileStream FS;
              private static int BytesPerChar;
              private static readonly object Locker = new object();
      
              public static void Start(string logFilePath, Encoding encoding = null)
              {
                  lock (Locker)
                  {
                      if (IsStarted) return;
                      LogFilePath = logFilePath;
                      Encoding = encoding ?? Encoding.UTF8;
                      if (File.Exists(LogFilePath)) File.SetAttributes(LogFilePath, FileAttributes.Normal);
                      FS = new FileStream(LogFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 4096, FileOptions.RandomAccess);
                      FS.SetLength(0);
                      FS.Flush();
                      BytesPerChar = Encoding.UTF8.GetByteCount(new[] { 'A' });
                      IsStarted = true;
                  }
              }
      
              public static void Close()
              {
                  lock (Locker)
                  {
                      if (!IsStarted) return;
                      try { FS?.Close(); } catch { }
                      FS = null;
                      IsStarted = false;
                  }
              }
      
              public static void WriteToFile(string text)
              {
                  lock (Locker)
                  {
                      if (string.IsNullOrEmpty(text)) return;
      
                      if (!text.Contains('\b'))
                      {
                          FS.Position = FS.Length;
                          byte[] bytes = Encoding.GetBytes(text);
                          FS.Write(bytes, 0, bytes.Length);
                          FS.Flush();
                          return;
                      }
      
                      // Evaluates the the string into initial backspaces and remaining text to be appended:
                      EvaluateText(text, out int initialBackspaces, out string remainingText);
      
                      // If there are no initial backspaces after evaluating the string, just append it and return:
                      if (initialBackspaces <= 0)
                      {
                          if (string.IsNullOrEmpty(remainingText)) return;
      
                          FS.Position = FS.Length;
                          byte[] bytes = Encoding.GetBytes(remainingText);
                          FS.Write(bytes, 0, bytes.Length);
                          FS.Flush();
                          return;
                      }
      
                      // First process the initial backspaces:
                      long pos = FS.Length - initialBackspaces * BytesPerChar;
                      FS.Position = pos > 0 ? pos : 0;
                      FS.SetLength(FS.Position);
      
                      // Then write any remaining evaluated text:
                      if (!string.IsNullOrEmpty(remainingText))
                      {
                          byte[] bytes = Encoding.GetBytes(remainingText);
                          FS.Write(bytes, 0, bytes.Length);
                      }
                      FS.Flush();
                      return;
                  }
              }
      
              public static void EvaluateText(string text, out int initialBackspaces, out string remainingTextToAppend)
              {
                  initialBackspaces = 0;
                  StringBuilder sb = new StringBuilder();
                  foreach (char ch in text)
                  {
                      if(ch == '\b')
                      {
                          if (sb.Length > 0) sb.Length--;
                          else initialBackspaces++;
                      }
                      else sb.Append(ch);
                  }
                  remainingTextToAppend = sb.ToString();
              }
          }
      }
      
      输出(test.log文件):

      阿克斯


      因此,您只想在附加到文件之前删除文件的最后n个字符?实际上,该字符串可能包含出现退格之前的字符。如所提供的示例中所示,字符串开头有三个点(.)字符。但该字符串确实将始终附加到文本文件中。(我已经编辑了这个示例,让它更清晰)简短的答案是否定的。长的答案是您必须使用某种描述的
      位置
      搜索
      文件流
      和一些好的老式文件流来构建自己的功能coding@TheGeneral考虑到编码,可能比使用
      文件流更复杂:-)(例如,参见提问者使用的刻痕)。遗憾的是,.NET中没有统一的
      StreamReaderWriter
      ,因此修改编码的文本文件变得很痛苦。@xanatos非常好,所以您只想在附加到文件之前删除文件的最后n个字符?实际上,字符串中可能包含空格之前的字符。如所提供的示例中所示,有开头有三个点(.)字符