java - 从 SQL Server 进行 Java 字节反序列化期间流头无效

标签 java sql-server serialization arrays deserialization

我需要在 SQL Server 2008 表中保存序列化的对象流,然后对其进行反序列化。当我反序列化时出现问题..我收到以下异常:

Exception in thread "main" java.io.StreamCorruptedException: invalid stream header: 5B424065
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:804)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299)

我使用 JTDS-1.2.4(不是最后一个 JTDS 驱动程序类型 4)

在表中,我保存在列类型 -> NVARCHAR(MAX) 中,我有这个值,例如

[B@e3fd79

我读了上面的值(jtds 给我一个 sql.Clob),然后我尝试反序列化它

我的Java代码:

    DocumentObjectHolder doc = new DocumentObjectHolder(xmldata, "data.xml", TYPE.XML, xmldata.getBytes("UTF-8"));
//SERIALIZE DocumentObjectHolder 
            ByteArrayOutputStream bof = new ByteArrayOutputStream();
            ObjectOutputStream serialize = new ObjectOutputStream(bof);
            serialize.writeObject(doc);
            SQLDbManagerFactory.setDbConnectionParameters(dbUri, username, password, driver);
            SQLDBManager factoryDb = SQLDbManagerFactory.getSQLDBManager();

            factoryDb.execSQL("INSERT INTO MY_DOCUMENTS (DATA,DOCUMENT_TYPE,IS_READY,DO_EMIT,IS_EMITTED)" + 
            " VALUES ( '" + bof.toByteArray() + "','" + TYPE.XML.name() + "', 0, 0, 0)");

            RecordSet rs = (RecordSet) factoryDb.execSQL("SELECT TOP 1 DATA FROM MY_DOCUMENTS");
            if (rs != null && rs.getLength() > 0){
//DESERIALIZE in DocumentObjectHolder 
                Clob objris = (Clob)rs.get(0, 0);  
                InputStream in = objris.getAsciiStream();
                byte[] b = new byte[in.available()];
                in.read(b);
                ByteArrayInputStream bais = new ByteArrayInputStream(b);
                ObjectInputStream ins = new ObjectInputStream(bais);
                DocumentObjectHolder mc =(DocumentObjectHolder)ins.readObject();
                System.out.println("Object in value ::"+mc.toString());
                ins.close();
                in.close();
            }

SQLDBManager 是我的私有(private)库..

我想这将是一个 Blob(字节 blob)而不是一个 Clob(char lob),所以我尝试将 nvarchar(max) 更改为 varbinary(500) 因为我在这里读到: http://jtds.sourceforge.net/typemap.html

但我得到以下异常:

Exception in thread "main" java.sql.SQLException: Invalid SQL statement or JDBC escape, terminating ']' not found.
at net.sourceforge.jtds.jdbc.SQLParser.parse(SQLParser.java:1155)
at net.sourceforge.jtds.jdbc.SQLParser.parse(SQLParser.java:156)
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.<init>(JtdsPreparedStatement.java:107)
at net.sourceforge.jtds.jdbc.ConnectionJDBC2.prepareStatement(ConnectionJDBC2.java:2456)
at net.sourceforge.jtds.jdbc.ConnectionJDBC2.prepareStatement(ConnectionJDBC2.java:2414)

出了什么问题?

最佳答案

让我们从“标题”5B424065开始。

如果将其翻译为 ASCII,则会得到 '[' 'B' '@' 'e' ... 这看起来很熟悉吗?

现在你的字符串“[B@e3fd79”。它是什么?

首先,它不是有效的序列化。事实上,它是什么......就是在 byte[] 上调用 toString() 时得到的结果。

  • "[B" 组件是 byte[] 的类型签名。

  • “e3fd79” 组件是身份哈希码...通常基于首次请求身份哈希码时的数组地址。

  • 最重要的是,该字符串不会对字节数组的内容进行编码/

那么它从哪里来?

它来自这个表达式:bof.toByteArray()。这不是将字节数组的内容转换为字符串的正确方法。

什么是正确的方法?

这取决于“DATA”列的 SQL 类型。是的 - @EJP 说得对。您根本不应该尝试对字节数组进行字符串化。使用 PreparedStatement 和参数占位符 (?)。

如果列类型是 BINARY 或 VARBINARY,那么您应该能够按原样传递 byte[]。有关 jDTS 类型映射的完整列表,请参阅 the documentation .

关于java - 从 SQL Server 进行 Java 字节反序列化期间流头无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30056492/

相关文章:

java - Note5读取Mifare经典卡UID

Java 相当于 struct.unpack ('d' 、 s.decode ('hex' ))[0]

sql-server - 添加附加行

sql-server - 如何在 SQL 中计算 IPv6 CIDR 路由前缀?

Wcf、序列化、只读成员

c# - 如何将类序列化为属性?

java - 客户端-服务器通信的可扩展性; XML v 序列化二进制文件

java - 将所有 `@QueryParam` 映射到 `JSON` 数据结构

java - 由 org.gdal.ogr.ogrJNI.GetDriverCount() 引起的 UnsatisfiedLinkError

sql-server - Freetds 无法通过服务器名称 (-S) 连接到 SQL Azure,但可以通过主机 (-H) 连接