You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

传输文件后输入流未关闭,客户端while循环无法退出求助

解决输入流无法退出while循环的问题

兄弟,我懂你这种卡在while循环里的痛苦!之前我也碰到过类似的问题,就是因为输入流不知道什么时候该停,一直堵在那儿没法往下执行播放逻辑。给你几个实用的解决办法,你可以根据自己的场景选:

方法一:先传文件大小,按需读取字节

这是最稳妥的方案,让服务器先把音乐文件的总字节数发过来,客户端拿到这个数值后,就知道要读多少字节才够,读完直接退出循环。

调整后的客户端代码大概是这样:

@Override 
protected Void call() { 
    try {
        // 假设你用的是Socket的输入流,包装成DataInputStream方便读取长整型
        DataInputStream dis = new DataInputStream(socket.getInputStream());
        
        // 第一步:读取服务器发来的文件总大小
        long totalFileSize = dis.readLong();
        byte[] buffer = new byte[1024]; // 缓冲区大小可以根据需求调整
        long bytesReadSoFar = 0;
        
        // 准备写入本地文件
        FileOutputStream fos = new FileOutputStream("saved_song.mp3");
        
        // 只要还没读完指定的字节数,就继续读
        while (bytesReadSoFar < totalFileSize) {
            int currentRead = dis.read(buffer);
            if (currentRead == -1) {
                // 意外断开连接,提前终止循环
                break;
            }
            fos.write(buffer, 0, currentRead);
            bytesReadSoFar += currentRead;
        }
        
        // 关闭流资源
        fos.close();
        dis.close();
        
        // 现在可以放心播放歌曲了!
        playSavedSong();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

方法二:服务器传完就关输出流

如果你的场景是一次性传输文件(不是长连接),让服务器在发送完所有音乐字节后,主动调用outputStream.close(),这样客户端的read()方法会返回-1,循环自然就终止了。

客户端代码可以这么写:

@Override 
protected Void call() { 
    try {
        InputStream is = socket.getInputStream();
        byte[] buffer = new byte[1024];
        int currentRead;
        
        FileOutputStream fos = new FileOutputStream("saved_song.mp3");
        
        // 当服务器关闭输出流后,read()会返回-1,循环结束
        while ((currentRead = is.read(buffer)) != -1) {
            fos.write(buffer, 0, currentRead);
        }
        
        // 关闭资源
        fos.close();
        is.close();
        
        // 执行播放逻辑
        playSavedSong();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

小提醒:UI线程注意事项

因为你这是UI应用的任务,千万别在call()方法里直接操作UI或者播放音频!比如Android里要用到runOnUiThread,Swing里用SwingUtilities.invokeLater,把播放逻辑切换到UI线程执行,不然容易出线程安全问题哦。

内容的提问来源于stack exchange,提问作者Lucky38i

火山引擎 最新活动