Java 将十六进制 UTF8 转换为 UTF-16
Java convert hex UTF8 to UTF-16
我正在通过数据捕获产品从大型机发送一些交易数据(json 格式)。在 JSON 中,它们应该发送一个值,该值是大型机 timeOfDay (TOD) 值,表示等效的事务时间戳。
而不是发送值 "stck":"00d2fde04305b72642"
他们反而寄给我 "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”
我找到了一个问题,该问题显示了如何使用 java 将生成的 TOD 值 ("stck":"00d2fde04305b72642") 转换为事务时间戳,因此我在该部分进行了介绍。
"They" 做错了。他们应该简单地以 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();
}
}
我正在通过数据捕获产品从大型机发送一些交易数据(json 格式)。在 JSON 中,它们应该发送一个值,该值是大型机 timeOfDay (TOD) 值,表示等效的事务时间戳。 而不是发送值 "stck":"00d2fde04305b72642"
他们反而寄给我 "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”
我找到了一个问题,该问题显示了如何使用 java 将生成的 TOD 值 ("stck":"00d2fde04305b72642") 转换为事务时间戳,因此我在该部分进行了介绍。
"They" 做错了。他们应该简单地以 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();
}
}