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

Java字节数组转WAV文件 分块加解密报不支持流格式异常求助

问题描述

编辑补充:感谢大家!问题已解决,需逐块解密并保留原始文件格式。

对音频文件按16字节大小分块加密后,解密输出文件时抛出Stream of unsupported format异常,涉及byte array转wav文件操作,相关实现代码如下:

public class Main {
public static void main(String[] args)
        throws InvalidKeyException, UnsupportedAudioFileException, IOException, LineUnavailableException {

    File decryptedFile = new File("dec.wav");
    File soundFile = new File("C:\\Users\\Daniel\\Desktop\\FROG1\\peeper5sec.wav");
    String k = "KEY";
    byte[] key = k.getBytes();
    
    Object keyKey=frog_Algorithm.makeKey(key);

    AudioInputStream st = AudioSystem.getAudioInputStream(soundFile);
    byte[][] fileInByte = split(st.readAllBytes(),16);
    
    if (fileInByte == null)
        fileInByte[0] = st.readAllBytes();

    byte enc[]=null;
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );

    
    for (int i = 0; i < fileInByte.length; i++) {
        byte tmp3[]=frog_Algorithm.blockEncrypt(fileInByte[i], 0, keyKey);
        outputStream.write(tmp3);
    }
    enc=outputStream.toByteArray();
    
    
            
    FileOutputStream fos=new FileOutputStream(decryptedFile.getAbsolutePath());
    
    //fos.AudioSystem.write(frog_Algorithm.blockDecrypt(enc, 0,keyKey));
     //fos.close();
    byte[] dec=frog_Algorithm.blockDecrypt(enc, 0,keyKey);
    for (int i = 0; i < dec.length; i++) {
        fos.write(dec[i]);
    }

    ByteArrayInputStream bais = new ByteArrayInputStream(dec);
    AudioInputStream stream = AudioSystem.getAudioInputStream(bais);
    
     AudioSystem.write(stream, getAudioFileFormat(stream), decryptedFile);
问题原因&解决方法

抛出异常的核心原因有4个:

  • 解密逻辑和加密逻辑不匹配:加密是按16字节逐块调用blockEncrypt处理,但解密时直接对整个密文数组单次调用blockDecrypt,没有和加密一样逐块解密,得到的明文数据是损坏的。
  • WAV文件格式信息丢失:调用st.readAllBytes()只读取了音频的裸帧数据,没有保留原WAV文件的格式参数(采样率、位深、声道数、编码规则),直接把纯音频字节流包装成ByteArrayInputStream传给AudioSystem时,系统无法从裸数据里识别音频格式,自然抛出不支持格式的异常。
  • 文件写入逻辑冲突:提前用FileOutputStream往目标文件写了解密后的字节,后面又调用AudioSystem.write往同一个文件写内容,会导致文件内容覆盖、错乱,而且代码全程没有关闭流的操作,会触发资源泄漏。
  • 边界逻辑bug:如果split方法返回null,直接执行fileInByte[0]赋值会触发空指针;且第一次调用st.readAllBytes()后流已经读到末尾,第二次调用readAllBytes()读不到任何有效数据。

修正步骤

  1. 读取原文件时第一时间保存原音频的AudioFormat和原始音频数据长度,解密后生成音频流时直接复用这些参数,不需要从裸字节流探测格式。
  2. 解密逻辑和加密逻辑完全对齐:把密文按16字节分块后逐块调用blockDecrypt,再把所有解密后的块拼接成完整的明文数组;如果最后一个块不足16字节,要和加密阶段使用的填充规则保持一致,避免解密后出现多余无效字节。
  3. 去掉提前用FileOutputStream写文件的冗余逻辑,所有流操作完成后及时关闭,避免资源泄漏和文件损坏。
  4. 删除存在空指针风险的null判断分支,读取音频数据时一次性读完,不要重复调用readAllBytes()。

修正后的核心代码参考:

public class Main {
public static void main(String[] args)
        throws InvalidKeyException, UnsupportedAudioFileException, IOException, LineUnavailableException {

    File decryptedFile = new File("dec.wav");
    File soundFile = new File("C:\\Users\\Daniel\\Desktop\\FROG1\\peeper5sec.wav");
    String k = "KEY";
    byte[] key = k.getBytes();
    
    Object keyKey = frog_Algorithm.makeKey(key);

    // 读取原文件时提前保存格式信息和原始数据
    AudioInputStream originalStream = AudioSystem.getAudioInputStream(soundFile);
    AudioFormat originalFormat = originalStream.getFormat();
    byte[] originalAudioData = originalStream.readAllBytes();
    int originalDataLen = originalAudioData.length;
    originalStream.close();

    // 分块加密
    byte[][] fileInByte = split(originalAudioData, 16);
    ByteArrayOutputStream encOut = new ByteArrayOutputStream();
    for (int i = 0; i < fileInByte.length; i++) {
        encOut.write(frog_Algorithm.blockEncrypt(fileInByte[i], 0, keyKey));
    }
    byte[] encData = encOut.toByteArray();

    // 逐块解密,和加密逻辑一一对应
    byte[][] encBlocks = split(encData, 16);
    ByteArrayOutputStream decOut = new ByteArrayOutputStream();
    for (int i = 0; i < encBlocks.length; i++) {
        decOut.write(frog_Algorithm.blockDecrypt(encBlocks[i], 0, keyKey));
    }
    byte[] decData = decOut.toByteArray();

    // 复用原音频格式构造流,直接输出WAV文件
    ByteArrayInputStream bais = new ByteArrayInputStream(decData);
    AudioInputStream decStream = new AudioInputStream(bais, originalFormat, originalDataLen);
    AudioSystem.write(decStream, AudioFileFormat.Type.WAVE, decryptedFile);
    decStream.close();
}

注意:如果分块时最后一个数据块不足16字节,需要按照FROG算法要求的填充规则补全后再加密,否则解密后末尾会出现多余的无效字节,导致音频播放末尾有杂音。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:54:31