代码之家  ›  专栏  ›  技术社区  ›  Helena

在打开的NamedPipeClientStream上重新创建UTF-8 StreamWriter会导致服务器上出现额外的BOM字符

  •  0
  • Helena  · 技术社区  · 2 年前

    我有一个 NamedPipeServerStream 保持开放 NamedPipeClientStream 保持开放。这个 命名管道服务器流 具有UTF-8 StreamReader 保持开放。这个 NamedPipeClientStream 具有UTF-8 StreamWriter 打开、写入一条消息、关闭然后重新打开以写入另一条消息。两个 StreamReader 以及 StreamWriter 使用打开 leaveOpen 标志设置为true,因此 StreamWriter 无法关闭 NamedPipeClientStream 当它关闭时。到目前为止,一切都很好。

    我有一个问题,从第二次 StreamWriter 打开并发送消息时 StreamReader 。我已经设法在一个小的示例程序中重新创建了它。它是在.NET6。这是示例程序的代码:

    using System.IO.Pipes;
    
    namespace NamedPipeTest
    {
        internal class EncodingTest
        {
            private static NamedPipeServerStream namedPipeServer = new NamedPipeServerStream("mypipe", PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
            private static NamedPipeClientStream namedPipeClient = new NamedPipeClientStream(".", "mypipe", PipeDirection.InOut, PipeOptions.Asynchronous);
    
            static void Main(string[] args)
            {
                Console.WriteLine("Hello! You are the client. Press any key to send a request.");
    
                Task[] tasks = new Task[]
                {
                    Task.Run(() => Server()),
                    Task.Run(() => Client())
                };
    
                Task.WaitAll(tasks);
            }
    
            static async Task Server()
            {
                if (!namedPipeServer.IsConnected)
                {
                    namedPipeServer.WaitForConnection();
                }
    
                using (var reader = new StreamReader(namedPipeServer, System.Text.Encoding.UTF8, false, 1024, true))
                {
                    while (true)
                    {
                        string? line = await reader.ReadLineAsync();
                        Console.WriteLine($"Server: Received request: {line}");
                        if (!string.IsNullOrEmpty(line))
                        {
                            var lineBytes = System.Text.Encoding.UTF8.GetBytes(line);
                            var possibleBOMString = System.Text.Encoding.UTF8.GetString(new byte[] { lineBytes[0], lineBytes[1], lineBytes[2] });
                            if (possibleBOMString.Equals("\uFEFF"))
                            {
                                Console.WriteLine("Server: Whoa, what's up with the extra BOM?");
                            }
                        }
                    }
                }
            }
    
            static async Task Client()
            {
                if (!namedPipeClient.IsConnected)
                {
                    namedPipeClient.Connect(6000);
                }
    
                while (true)
                {
                    using (var writer = new StreamWriter(namedPipeClient, System.Text.Encoding.UTF8, 1024, true))
                    {
                        Console.ReadKey(true);
                        Console.WriteLine("Client: Received key press, sending request.");
                        string? line = "Hello!";
                        await writer.WriteLineAsync(line);
                        await writer.FlushAsync();
                        Console.WriteLine($"Client: Sent request: {line}");
                    }
                }
            }
        }
    }
    

    该程序的输出为:

    Hello! You are the client. Press any key to send a request.
    Client: Received key press, sending request.
    Server: Received request: Hello!
    Client: Sent request: Hello!
    Client: Received key press, sending request.
    Server: Received request: ?Hello!
    Client: Sent request: Hello!
    Server: Whoa, what's up with the extra BOM?
    Client: Received key press, sending request.
    Server: Received request: ?Hello!
    Client: Sent request: Hello!
    Server: Whoa, what's up with the extra BOM?
    

    这种情况无休止地持续着。因此,该行在发送时不包含额外的BOM,而是在被 StreamReader 。这里发生了什么事?

    0 回复  |  直到 2 年前
        1
  •  1
  •   shingo    2 年前
    1. System.Text.Encoding.UTF8 provides a BOM

    它返回一个UTF8Encoding对象,该对象提供Unicode字节顺序标记(BOM)。

    1. StreamWriter.FlushAsync appends a BOM 流。

    2. StreamWriter.Dispose 将呼叫 Flush ,因此它还附加了一个BOM表。

    解决方案是构造一个自定义的UTF8Encoding对象:

    var enc = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
    ...
    using (var writer = new StreamWriter(namedPipeClient, enc, 1024, true))
    
    推荐文章