You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift通过流读取Java服务端PrintWriter字符串返回-1如何解决?

问题根因
  1. 你当前提供的Swift代码仅包含输出流写入逻辑,没有实现输入流读取服务端返回数据的相关代码,你提到的bytesWritten是输出流写入操作的返回值,返回-1代表输出流写入失败,和读取逻辑无关。
  2. Swift的Stream实例必须先调用open()方法、等待流进入就绪状态后才能执行读写操作,未就绪直接读写会直接返回-1。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 19:06:03