Swift通过流读取Java服务端PrintWriter字符串返回-1如何解决?
问题根因
- 你当前提供的Swift代码仅包含输出流写入逻辑,没有实现输入流读取服务端返回数据的相关代码,你提到的
bytesWritten是输出流写入操作的返回值,返回-1代表输出流写入失败,和读取逻辑无关。 - Swift的
Stream实例必须先调用open()方法、等待流进入就绪状态后才能执行读写操作,未就绪直接读写会直接返回-1。 - Java端
OutputStreamWriter未显式指定编码,默认会使用操作系统默认编码,和Swift端默认使用的UTF-8编码可能不匹配,导致数据传输异常。
修复代码
Java服务端修改
显式指定输出编码为UTF-8,保证双端编码一致:
import java.nio.charset.StandardCharsets; PrintWriter out = null; try { // 显式指定UTF-8编码,避免系统默认编码导致的不兼容问题 out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(tempClientSocket.getOutputStream(), StandardCharsets.UTF_8)), true); } catch (IOException e) { e.printStackTrace(); } out.println("hello world"); // 写入完成后如果不需要继续传输可以主动关闭输出流,避免粘包问题 // out.close(); // tempClientSocket.shutdownOutput();
Swift客户端修改
首先需要正确处理流的状态监听,先执行写入操作,再监听输入流的可读事件读取服务端返回:
import Foundation // 首先需要设置流的代理监听流状态变化 class StreamHandler: NSObject, StreamDelegate { var inputStream: InputStream? var outputStream: OutputStream? func setupStream(host: String, port: Int) { var readStream: Unmanaged<CFReadStream>? var writeStream: Unmanaged<CFWriteStream>? // 创建TCP流连接 CFStreamCreatePairWithSocketToHost(nil, host as CFString, UInt32(port), &readStream, &writeStream) inputStream = readStream?.takeRetainedValue() outputStream = writeStream?.takeRetainedValue() inputStream?.delegate = self outputStream?.delegate = self // 必须调用open方法启动流 inputStream?.schedule(in: .current, forMode: .common) outputStream?.schedule(in: .current, forMode: .common) inputStream?.open() outputStream?.open() } func stream(_ aStream: Stream, handle eventCode: Stream.Event) { switch eventCode { case .hasSpaceAvailable: // 输出流有可用空间时才执行写入操作 guard aStream == outputStream else { return } let data = "hello".data(using: .utf8)! let dataCount = data.count let bytesWritten = data.withUnsafeBytes { p in return outputStream?.write(p.baseAddress!.assumingMemoryBound(to: UInt8.self), maxLength: dataCount) ?? -1 } print("写入字节数:\(bytesWritten)") case .hasBytesAvailable: // 输入流有数据可读时读取服务端返回 guard aStream == inputStream else { return } let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 1024) let bytesRead = inputStream?.read(buffer, maxLength: 1024) ?? 0 if bytesRead > 0 { let receivedData = Data(bytes: buffer, count: bytesRead) if let receivedStr = String(data: receivedData, encoding: .utf8) { print("收到服务端返回:\(receivedStr)") } } buffer.deallocate() case .errorOccurred: print("流发生错误:\(aStream.streamError?.localizedDescription ?? "未知错误")") default: break } } }
常见写入返回-1排查点
- 输出流未调用
open()方法就直接执行写操作 - TCP连接已断开,流处于关闭状态
- 未等待输出流
hasSpaceAvailable事件触发就直接写入,流无可用写入空间 - 双端编码不匹配导致数据写入异常
内容的提问来源于stack exchange,提问作者fareeha naz
相关产品推荐
相关产品推荐

