序列化 java.util.Date

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4433198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 17:24:48  来源:igfitidea点击:

Serializing java.util.Date

javaserialization

提问by BigMac66

Does anyone know how a java.util.Date gets serialized? I mean explain to me exactly what each byte is? I tried writing out a long then a date and I can see matches but there are other characters that I just don't get.

有谁知道 java.util.Date 是如何序列化的?我的意思是向我解释每个字节是什么?我试着写出一个很长的日期,我可以看到匹配项,但还有其他字符我就是不明白。

Our application makes server requests with data which means it gets serialized from client to server. The team that does stress testing uses a tool that captures these requests and modifies them, the problem is they want to process dates and I don't know how to interpret the byte stream. The dude I am talking to seems willing to learn but so far I haven't found anything that I understand to point him to...

我们的应用程序使用数据向服务器发出请求,这意味着它会从客户端序列化到服务器。做压力测试的团队使用一个工具来捕获这些请求并修改它们,问题是他们想要处理日期而我不知道如何解释字节流。我正在与之交谈的那个人似乎愿意学习,但到目前为止我还没有找到任何我理解的东西来指向他......

Code I used:

我使用的代码:

  FileOutputStream fos = null;
  ObjectOutputStream oos = null;
  try
  {
   fos = new FileOutputStream("t.tmp");
   oos = new ObjectOutputStream(fos);

   Date today = new Date();

   oos.writeLong(today.getTime());
   oos.writeObject("Today");
   oos.writeObject(today);

   oos.close();
  }
  catch(FileNotFoundException e)
  {
   e.printStackTrace();
  }
  catch(IOException e)
  {
   e.printStackTrace();
  }

EDIT:

编辑:

The output from the above is:

上面的输出是:

"?í w  ,áq?-t Todaysr java.util.DatehjKYt  xpw  ,áq?-x"

The long is "w ,áq?-" so what is the stuff between the long and the Date object, i.e. "hjKYt xp"

long 是 "w ,áq?-" 那么 long 和 Date 对象之间的内容是什么,即 "hjKYt xp"

NOTE some the blanks are unprintable characters NULL, SOH, backspace etc. I understand that it is the hex value that matters.

注意一些空白是不可打印的字符 NULL、SOH、退格等。我知道重要的是十六进制值。

EDIT:

编辑:

Still having problems. For some reason the serialized HTTP request does not serialize the date exactly like the answer I accepted says. Very close but still different and I don't know why. What's even odder is that when I simply serialize a date it seems to work fine. FYI at worj we use Websphere 6.1 Here are some examples of what is being sent in the request:

还是有问题。出于某种原因,序列化的 HTTP 请求不会像我接受的答案所说的那样序列化日期。非常接近但仍然不同,我不知道为什么。更奇怪的是,当我简单地序列化一个日期时,它似乎工作正常。仅供参考,我们使用 Websphere 6.1 以下是请求中发送内容的一些示例:

 lr_start_transaction("20000101");
\x0Ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\x08\x00\x00\x01,\xE10\x0BXxt\x00\x08

 lr_start_transaction("20000102");
\x0Ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\x08\x00\x00\x01,\xE10>\x9Dxt\x00\x08

 lr_start_transaction("20000103");
\x0Ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\x08\x00\x00\x01,\xE10z\xDBxt\x00\x08

I have been able to identify most fields but not the actual time! E.g the serialVersionUID is hj\\x81\\x01KYt\\x19

我已经能够识别大多数字段,但不能识别实际时间!例如,serialVersionUID 是hj\\x81\\x01KYt\\x19

EDIT (FINAL):

编辑(最终):

I found the date but it was no where near where I expected it! It was well after the sample I had because other data fields were appearing I thought the date was done - it was just fluke that I noticed the hex pattern of the date I was looking for! Example:

我找到了日期,但离我预期的很近!在我拥有的样本之后很好,因为其他数据字段出现了我认为日期已经完成 - 我注意到我正在寻找的日期的十六进制模式只是侥幸!例子:

 lr_start_transaction("20000101");
\x0Ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\x08\x00\x00\x01,\xE10\x0BXxt\x00\x08OTTST153t\x00\x06/Web2/t\x00\x044971t\x00\x0B12ce12f737d\x00\x00\x01,\xE10\x0BXsq\x00~\x00\x0Fw\x08\x00\x00\x00\xDCk\xE2T\x80xt

The date value is right at the very end!

日期值就在最后!

采纳答案by pstanton

/**
 * Save the state of this object to a stream (i.e., serialize it).
 *
 * @serialData The value returned by <code>getTime()</code>
 *         is emitted (long).  This represents the offset from
 *             January 1, 1970, 00:00:00 GMT in milliseconds.
 */
private void writeObject(ObjectOutputStream s)
     throws IOException
{
    s.writeLong(getTimeImpl());
}

therefore, it's the long value representing the offset from Jan 1 1970 00:00:00 GMT in milliseconds.

因此,它是表示从 1970 年 1 月 1 日 00:00:00 GMT 开始的以毫秒为单位的偏移量的 long 值。

EDIT: however this is preceeded and succeeded by some headers:

编辑:然而,这是在一些标题之前和之后的:

0x73 - being the code for an ordinary object (TC_OBJECT)    
0x72 - being the code for a class description (TC_CLASSDESC)    
"java.util.Date" - the name of the class    
7523967970034938905L - the serialVersionUID    
0|0x02|0x01 - flags including SC_SERIALIZABLE & SC_WRITE_METHOD    
0 - number of fields    
0x78 - TC_ENDBLOCKDATA    
null - there is no superclass descriptor    
the time (long milliseconds since epoch)    
0x78 - TC_ENDBLOCKDATA

回答by Tom Hawtin - tackline

The details of the format of Java object serialisation are specified in Java Object Serialization Specification. Other than magic and version numbers , details of the Dateclass and the fact the object is a Dateis written to the stream.

Java 对象序列化格式的详细信息在Java 对象序列化规范中指定。除了 magic 和 version numbers ,Date类的详细信息和对象是 a 的事实Date被写入流。

The API doc for Dateserialised formis:

序列化形式API 文档Date是:

The value returned by getTime() is emitted (long). This represents the offset from January 1, 1970, 00:00:00 GMT in milliseconds.

getTime() 返回的值被发出(长)。这表示从 1970 年 1 月 1 日 00:00:00 GMT 开始的以毫秒为单位的偏移量。

Note that it actually breaks the spec by not calling defaultWriteObjector putFields.

请注意,它实际上通过不调用defaultWriteObjector 来打破规范putFields