Java将十六进制UTF8转换为UTF-16

时间:2017-08-16 03:53:10

标签: java encoding utf-8 character-encoding utf

我正在通过数据捕获产品从大型机发送一些交易数据(以json格式)。在JSON中,它们应该发送一个值,该值是大型机timeOfDay(TOD)值,表示等效的事务时间戳。 而不是发送值“stck”:“00d2fde04305b72642”

他们反而向我发送“stck”:“\ u00c3 \ u00c \ u00c \ u00c \ u00c \ u00c \ u00c \ u00c \ u00c \ u00c \ u00c \ u00c \ u00c \ u00c 当我问他们为什么说“

“上面的内容(”stck“:”00d2fde04305b72642“)是二进制数据UTF-16格式.JSON不能很好地处理二进制数据,所以我们将其转换为十六进制UTF-8格式。你可以转换它回到你身边的UTF-16“

我需要在java中帮助这样做。我已经看到了多个问题,但没有什么能完全符合我的要求,将十六进制UTF-8转换为UTF-16,希望看起来像“00d2fde04305b72642”

我已经能够找到一个问题,显示如何使用java将这个产生的TOD值(“stck”:“00d2fde04305b72642”)转换为事务时间戳,所以我在那部分内容已经涵盖了。

1 个答案:

答案 0 :(得分:1)

"他们"做错了。他们应该简单地对base-16中的数值进行编码并使用结果字符串。

他们正在做的是将数值的字节视为字符,并使用UTF-8对它们进行编码。然后,他们获取这些字节并在非ASCII字符上应用Unicode转义序列。当被问及这个过程时,当他们对伤害进行侮辱时,他们的回答是胡说八道。它在很多层面都是一场灾难。

以下内容应该允许您恢复数据并转换为Java时间戳。

import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;

public class SO45704851
{

  public static void main(String... argv)
    throws Exception
  {
    String example = "\u00c3\u0092\u00c3\u00bd\u00c2\u00aa\u00c2\u009e\u001c\u00c2\u0089\u001cG";
    long tod = sbrogliare(example);
    System.out.printf("ToD: 0x%016x%n", tod);
    Instant time = toInstant(tod);
    System.out.printf("Instant: %s%n", time);
  }

  /**
   * Clean up an infernal mess, miraculously bestowing a 64-bit time-of-day.
   */
  public static long sbrogliare(String garbage)
  {
    byte[] utf8 = new byte[garbage.length()];
    for (int idx = 0; idx < garbage.length(); ++idx)
      utf8[idx] = (byte) garbage.charAt(idx);
    String raw = new String(utf8, StandardCharsets.UTF_8);
    if (raw.length() != 8)
      throw new IllegalArgumentException();
    long n = 0;
    for (int idx = 0; idx < raw.length(); ++idx) {
      char ch = raw.charAt(idx);
      if (ch > 255)
        throw new IllegalArgumentException();
      n = n << 8 | ch;
    }
    return n;
  }

  private static final OffsetDateTime zero = OffsetDateTime.parse("1900-01-01T00:00Z");

  /**
   * Convert 64-bit time-of-day to {@code Instant}.
   */
  public static Instant toInstant(long tod)
  {
    long nanos = (125 * (tod >>> 32) << 23) + (125 * (tod & 0xFFFFFFFFL) >>> 9);
    return zero.plus(nanos, ChronoUnit.NANOS).toInstant();
  }

}