Java转C#Socket流开发:逐行发送CSV数据时服务端接收异常排查
问题根因
你遇到的服务端收不到有效数据的问题,核心是代码实现和原Java逻辑的细节差异导致的,不存在复杂的特殊配置问题:
- 最关键的差异:Java原代码里循环调用的是
out.println(line),这个方法会在你读到的行内容末尾自动追加换行符。而你在C#代码里用的是output.Write(line),只会原样输出从CSV读到的行内容,完全不附加换行。
不管是Java的BufferedReader还是C#的StreamReader,ReadLine()方法的特性都是:读取到行结束符(换行/回车)后,会把行内容返回,同时会把行末尾的结束符从返回值里去掉。而你对接的服务端,大概率是按照「收到换行符才算完整一行数据」的规则做报文解析的,你只发内容不发行结束符,服务端就会一直卡在等待行尾的状态,没法把收到的字节流解析成有效数据,表现出来就是收不到正确内容。 - 你之前疑惑的
PrintWriter out = new PrintWriter(fg.getOutputStream())的等效实现,其实C#里的StreamWriter就是完全对应的类,你之前选的类本身没有错,只是调用的输出方法不对:把output.Write(line)替换为output.WriteLine(line),就和Java的println行为完全一致,会自动为每行追加匹配平台的换行符。
额外注意的实现细节
避免后续再踩同类坑,这几个点可以参考:
- 创建
StreamWriter的时候建议显式指定编码,不要用默认无参构造,避免和Java的默认编码、服务端的解码规则不一致,出现乱码问题。写法参考:new StreamWriter(stream, Encoding.UTF8),对齐Java常见的UTF-8编码默认值。 StreamWriter默认在被释放/关闭的时候,会连带把它包装的底层网络流、甚至关联的Socket一起关掉。如果需要单独操作底层网络资源,可以在构造时传入leaveOpen: true参数,避免Writer被关闭后直接断开Socket连接。- 原Java代码里逐行写完立刻
flush的逻辑你是写对的:StreamWriter和Java的PrintWriter类似,自带内存缓冲区,如果不手动flush,写入的内容会存在缓冲区里,直到攒够一定大小才会真正发送到网络,达不到原代码逐行发送、每行间隔100ms的时序要求。
修正后的等效C#实现代码
using System; using System.IO; using System.Net.Sockets; using System.Text; using System.Threading; // 等效原Java的Socket连接初始化 using TcpClient client = new TcpClient("localhost", 5400); using NetworkStream networkStream = client.GetStream(); // 等效原Java的BufferedReader+FileReader,读取CSV文件 using StreamReader fileReader = new StreamReader("reg_flight.csv", Encoding.UTF8); // 等效原Java的PrintWriter,指定UTF-8编码、关闭Writer时不中断底层网络连接 using StreamWriter socketWriter = new StreamWriter(networkStream, Encoding.UTF8, leaveOpen: true); string currentLine; while ((currentLine = fileReader.ReadLine()) != null) { Console.WriteLine(currentLine); // 等效Java的println:输出行内容+换行符 socketWriter.WriteLine(currentLine); // 等效Java的flush:立刻把缓冲区内容推送到网络 socketWriter.Flush(); // 等效Java的线程休眠100ms Thread.Sleep(100); } // 按原Java顺序释放资源 socketWriter.Close(); fileReader.Close(); client.Close();
内容的提问来源于stack exchange,提问作者spano
相关产品推荐
相关产品推荐

