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

如何通过JDBC读取经COMPRESS()压缩的H2数据库BLOB列数据?

在JDBC客户端手动解压H2 COMPRESS()生成的DEFLATE数据

嘿,刚好我对H2的COMPRESS函数格式比较熟悉,这就给你捋清楚怎么在客户端手动解压,不用依赖数据库的DECOMPRESS()函数!

首先得明确一个关键细节:H2的COMPRESS()函数输出的字节流并不是纯DEFLATE压缩数据,它前面加了4字节的自定义头部。具体结构是:

  • 前2字节:魔数0x4852(也就是ASCII的"HR",代表H2压缩)
  • 后2字节:压缩格式标识,DEFLATE对应的是0x0001

所以你直接用Java标准的解压工具会失败,必须先跳过这4个字节,再处理真正的压缩数据。

下面是完整的JDBC客户端解压示例代码(Java):

import java.io.*;
import java.sql.*;
import java.util.Arrays;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import java.nio.charset.StandardCharsets;

public class H2CompressedBlobReader {
    public static void main(String[] args) {
        String url = "jdbc:h2:/path/to/your/database";
        String user = "your_user";
        String pwd = "your_password";

        try (Connection conn = DriverManager.getConnection(url, user, pwd);
             PreparedStatement stmt = conn.prepareStatement("SELECT compressed_data FROM foo");
             ResultSet rs = stmt.executeQuery()) {

            if (rs.next()) {
                // 从ResultSet读取mediumblob字节数组
                byte[] compressedBlob = rs.getBytes("compressed_data");
                
                // 跳过H2的4字节头部,获取纯DEFLATE压缩数据
                byte[] deflatePayload = Arrays.copyOfRange(compressedBlob, 4, compressedBlob.length);
                
                // 使用InflaterInputStream解压(注意要传入true,告诉Inflater不需要ZIP头)
                try (ByteArrayInputStream bais = new ByteArrayInputStream(deflatePayload);
                     InflaterInputStream inflaterStream = new InflaterInputStream(bais, new Inflater(true));
                     InputStreamReader reader = new InputStreamReader(inflaterStream, StandardCharsets.UTF_8)) {

                    // 读取解压后的字符串
                    StringBuilder sb = new StringBuilder();
                    char[] buffer = new char[1024];
                    int read;
                    while ((read = reader.read(buffer)) != -1) {
                        sb.append(buffer, 0, read);
                    }

                    System.out.println("解压结果:" + sb.toString()); // 应该输出"Test"
                }
            }
        } catch (SQLException | IOException e) {
            e.printStackTrace();
        }
    }
}

几个关键注意点:

  • 跳过头部:一定要跳过前4字节,否则Inflater会因为输入数据格式不正确抛出异常
  • Inflater参数:new Inflater(true)这个参数很重要,它告诉Inflater处理的是纯DEFLATE数据,不需要解析ZIP格式的头部校验信息。如果不传true,默认会寻找ZIP头,导致解压失败
  • 字符编码:因为你存储的时候用了STRINGTOUTF8(),所以解压后要用UTF-8编码转成字符串,保证内容正确

这个方案完全在客户端处理,不会依赖数据库的DECOMPRESS()函数,完美兼容其他系统的需求!

内容的提问来源于stack exchange,提问作者André Risnes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:05:34