2017-08-16 74 views
-1

我正在通過數據捕獲產品從大型機發送一些事務數據(採用json格式)。在JSON中,它們應該發送一個值爲大型機timeOfDay(TOD)的值,該值指示等價的交易時間戳。 而是發送值 「STCK」 的: 「00d2fde04305b72642」Java將十六進制UTF8轉換爲UTF-16

他們,而不是送我 「STCK」:「\ u00c3 \ u0092 \ u00c3 \ u00bd \ u00c2 \ u00aa \ u00c2 \ u009e \ u001c \ u00c2 \ u0089 \ u001cG」

當我問他們爲什麼,他們說

‘以上(’STCK‘:’00d2fde04305b72642" )是二進制數據UTF-16格式JSON沒有處理二進制數據很好地工作,所以我們已經轉換。即UTF-8格式,而且你可以將它轉換回UTF-16在你身邊「

我需要在java中這樣做。我已經看到了多個問題,但沒有什麼正是我想要做的就是將十六進制UTF-8轉換爲UTF-16,應該看起來像「00d2fde04305b72642」

我已經能夠找到一個問題,顯示如何將這個結果TOD值(「stck」:「00d2fde04305b72642」)轉換爲使用java的事務時間戳記,因此我在該部分進行了介紹。

+0

我給上面的背景,但本質上我的問題是如何將上述十六進制轉換UTF-8值(\ u00c3 \ u0092 \ u00c3 \ u00bd \ u00c2 \ u00aa \ u00c2 \ u009e \ u001c \ u00c2 \ u0089 \ u001cG)爲00d2fde04305b72642的值...使用java .... 是否需要將此UTF-8轉換爲UTF-16才能轉換爲00d2fde04305b72642 ..對我而言不重要 – garryS

+0

這些字符串是否代表單個值?我想解開這個數字造成的腐敗腐敗是'd2fdaa9e1c891c47',而不是'd2fde04305b72642'。是否有可能包含兩種不同時間戳的信息? – erickson

+1

術語_「二進制數據UTF-16格式」非常值得懷疑 - UTF-8和UTF-16是表示字符串的方法,而不是時間戳等二進制信息,除非時間戳被格式化爲字符串。如果某人已經採用二進制值,將其解釋爲UTF-8,然後將其編碼爲UTF-16,那麼對於大量可能的二進制字符串將不起作用,所以這裏發生的事情還不清楚。另外,在所謂的UTF-16字符串的末尾有什麼「G」?這裏似乎沒有足夠的信息來提供有效的問題。 –

回答

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(); 
    } 

} 
+0

謝謝ton @ erickson。它完美地完成了這項工作。 – garryS