【问题标题】:Special Characters in StreamWriterStreamWriter 中的特殊字符
【发布时间】:2012-03-07 10:24:06
【问题描述】:

我正在使用 streamwriter 将字符串写入流。现在,当我从流中访问数据时,它会将“\0\0\0”字符添加到内容的末尾。我必须附加流内容,因此会产生问题,因为我无法通过 trim() 或 remove() 或 replace() 方法删除这些字符。

下面是我正在使用的代码:

写作:

using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
    using (StreamWriter writer = new StreamWriter(stream, System.Text.Encoding.Unicode))
    {
        try
        {
            string[] files = System.IO.Directory.GetFiles(folderName, "*.*", System.IO.SearchOption.AllDirectories);
            foreach (string str in files)
            {
                writer.WriteLine(str);
            }
            // writer.WriteLine(folderName);
        }
        catch (Exception ex)
        {
            Debug.WriteLine("Unable to write string. " + ex);
        }
        finally
        {
            mutex.ReleaseMutex();
            mutex.WaitOne();
        }
    }
}

供阅读:

 StringBuilder sb = new StringBuilder();
            string str = @"D:\Other Files\Test_Folder\New Text Document.txt";
 using (var stream = mmf.CreateViewStream())
                {
                    System.IO.StreamReader reader = new System.IO.StreamReader(stream);
                    sb.Append(reader.ReadToEnd());
                    sb.ToString().Trim('\0');
                    sb.Append("\n" + str);
                }

我怎样才能防止这种情况发生?

[更新] 写作

// Lock
            bool mutexCreated;
            Mutex mutex = new Mutex(true, fileName, out mutexCreated);
            if (!mutexCreated)
                mutex = new Mutex(true);
            try
            {
                using (MemoryMappedViewStream stream = mmf.CreateViewStream())
                {
                    using (BinaryWriter writer = new BinaryWriter(stream))
                    {
                        try
                        {
                            string[] files = System.IO.Directory.GetFiles(folderName, "*.*", System.IO.SearchOption.AllDirectories);
                            foreach (string str in files)
                            {
                                writer.Write(str);
                            }
                            writer.Flush();
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine("Unable to write string. " + ex);
                        }
                        finally
                        {
                            mutex.ReleaseMutex();
                            mutex.WaitOne();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Unable to monitor memory file. " + ex);
            }

阅读

StringBuilder sb = new StringBuilder();
            string str = @"D:\Other Files\Test_Folder\New Text Document.txt";
            try
            {
                using (var stream = mmf.CreateViewStream())
                {
                    System.IO.BinaryReader reader = new System.IO.BinaryReader(stream);
                    sb.Append(reader.ReadString());
                    sb.Append("\n" + str);
                }
                using (var stream = mmf.CreateViewStream())
                {
                    System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream);
                    writer.Write(sb.ToString());
                }
                using (var stream = mmf.CreateViewStream())
                {
                    System.IO.BinaryReader reader = new System.IO.BinaryReader(stream);
                    Console.WriteLine(reader.ReadString());
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Unable to monitor memory file. " + ex);
            }

【问题讨论】:

  • 写完文件后你试过 writer.Flush() 吗?
  • 刚刚尝试使用 writer.Flush() 但注意工作..
  • 我认为流不会在内容末尾添加任何内容。 '\0\0\0\' 终止符字符串取决于编码。这个answer 可能很有用。
  • using() 表示 Flush,但可能会将 Mutex 代码移出写入块。
  • 并使用明确的 Unicode 编码创建您的阅读器。

标签: c# streamwriter


【解决方案1】:

StreamWriter 没有附加“\0”。这些只是内存映射文件的内容,是您开始编写之前的内容。 StreamReader 需要一个文件结束指示器来知道何时停止读取。 mmf 中没有任何超出该部分的 size 的内容。就像您传递给 MemoryMappedFile.CreateNew(string, long) 的第二个参数一样。

或者换句话说,您创建了一个太大而无法容纳流的 mmf。好吧,当然,你没有时间机器来猜测它有多大。你肯定需要做点什么,修剪零点还不够好。第二次编写更短的流时会出错。阅读器现在仍将看到来自先前流内容的字节,并且它们不会为零。

否则,这对于 mmfs 来说是一个常见的问题,它们只是内存块,而流是对它的一个非常糟糕的抽象。 .NET 支持 mmfs 的重要原因之一是,尽管它们是一个非常核心的操作系统功能。您需要指针来映射 mmf,而托管语言不支持这一点。

在这种情况下,我看不到教 StreamReader 新技巧的好方法。将字节从 mmf 复制到 MemoryStream 可以解决问题,但会破坏 mmf 的要点。

考虑改用管道。

【讨论】:

    【解决方案2】:

    MMF 和 TextWriter/TextReader 的组合,尤其是 ReadToEnd() 不是很好的匹配。

    textReader 需要底层文件的 EOF 概念,而 MMF 只是不以相同的方式提供它。你的字符串中会塞满\0\0...,达到 MMF 的容量。

    作为一种可能的解决方法:

    • 收集要写入 StringBuilder 的字符串
    • 使用 BinaryWriter 将其写为 1 个字符串
    • 使用 BinaryReader 将其读回。

    另一个选项是使用 WriteLine/ReadLine 并定义一些 EOF 标记(空行或特殊字符串)。

    BinaryWriter 将在字符串前面加上一个长度前缀,以便 Reader 知道何时停止。

    【讨论】:

    • 当我尝试使用 ReadString() 方法从 BinaryReader 读取数据时,它只返回一个第一行。如何从阅读器中检索所有数据?
    • 它应该返回整个字符串,包括'\n'。检查您的写作代码或发布两部分。
    • 编辑您的问题,发布第二部分。
    • 我刚刚发布了写作和阅读代码。请查阅。在编写代码中,有三个文件路径,我正在写入 MMF 文件。在阅读代码时,首先我正在阅读现有的 MMF,然后将另一个文件路径附加到其中。
    • 重新更新:很明显,您正在编写多个字符串并且只读取 1 个。再次阅读我的第一个和第二个项目符号。
    猜你喜欢
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    • 2012-09-08
    • 2011-07-28
    • 2010-09-21
    • 2014-06-29
    相关资源
    最近更新 更多