5

私は次のことをしたいと思います...

a) 生成された UUID を長さ 8 の文字列に圧縮します。

b) 圧縮された UUID を解凍して元の UUID に戻します。

その理由は、UUID を提携システムに送信する必要があり、提携システムが UUID に 8 文字しか受け入れず、提携システムへの変更を要求できないためです。

残りは、私が持っている UUID を 8 文字の文字列に圧縮し、パートナー システムからメッセージが返されたときに元の UUID に解凍することです。

何か案は?

ありがとう。

4

3 に答える 3

10

情報理論上の理由から、あなたが求めることは不可能です。

RFC 4122で指定されているUUIDはUUID、Javaのオブジェクトと同様に128ビットです。

JavaStringは1文字あたり16ビットを格納できるため、8弦になります。charただし、すべてのビットシーケンスが有効なUTF-16文字列であるとは限らないため、8文字で128ビット未満の情報を格納できます。

したがって、UUIDを有効な8文字の文字列に圧縮すると、情報が失われるため、通常、UUIDを解凍して元のUUIDを取得する方法はありません。

意図したのは、一意の識別子として使用する短い文字列を生成することです。その場合は、 8文字のみのUUIDの生成を参照してください。

于 2012-08-06T03:15:13.593 に答える
0

char次のように、UUIDを実際には16ビット8要素のシーケンスである文字列に変換できます。

static String encodeUuid(final UUID id) {
  final long hi = id.getMostSignificantBits();
  final long lo = id.getLeastSignificantBits();
  return new String(new char[] {
    (char) ((hi >>> 48) & 0xffff), (char) ((hi >>> 32) & 0xffff),
    (char) ((hi >>> 16) & 0xffff), (char) ((hi       ) & 0xffff),
    (char) ((lo >>> 48) & 0xffff), (char) ((lo >>> 32) & 0xffff),
    (char) ((lo >>> 16) & 0xffff), (char) ((lo       ) & 0xffff)
  });
}

static UUID decodeUuid(final String enc) {
  final char[] cs = enc.toCharArray();
  return new UUID(
    (long) cs[0] << 48 | (long) cs[1] << 32 | (long) cs[2] << 16 | (long) cs[3],
    (long) cs[4] << 48 | (long) cs[5] << 32 | (long) cs[6] << 16 | (long) cs[7]
  );
}

このコードは確かに機能するように見え(ここで自分で試してみてください)、ほとんどの場合問題なくUTF-8とUTF-16の両方を使用してエンコード/デコードできます。

static boolean validate(final UUID id, final Charset cs) {
  final ByteBuffer buf = cs.encode(encodeUuid(id));
  final UUID _id = decodeUuid(cs.decode(buf).toString());
  return id.equals(_id);
}

public static void main(final String[] argv) {
  final UUID id = UUID.randomUUID();
  assert validate(id, StandardCharsets.UTF_8)  : "failed using utf-8";
  assert validate(id, StandardCharsets.UTF_16) : "failed using utf-16";
}

C:\dev\scrap>javac UuidTest.java

C:\dev\scrap>java -ea UuidTest

ただし、実際には、一部のUTF-16コードポイントがサロゲートとして予約されているという問題があります。この場合、エンコーディングは機能せず、元のUUIDを再構築できなくなります。詳細については、上記のメカニカルカタツムリの応答を参照してください。


UUID.randomUUIDを介して生成されたエンコードされたUUIDから一貫して実際に削除できる唯一のデータは、 (always )に使用される2ビットと(always )に使用される4ビットです。variant2version4

これらのグローバル識別子にはさまざまなバリエーションがあります。このクラスのメソッドは、Leach-Salzバリアントを操作するためのものですが、コンストラクターではUUIDの任意のバリアント(以下で説明)を作成できます。

バリアント2(Leach-Salz)UUIDのレイアウトは次のとおりです。最も重要なlongは、次の符号なしフィールドで構成されます。 0xFFFFFFFF00000000 time_low
0x00000000FFFF0000 time_mid
0x000000000000F000 version
0x0000000000000FFF time_hi

最下位のlongは、次の符号なしフィールドで構成されます。 0xC000000000000000 variant
0x3FFF000000000000 clock_seq
0x0000FFFFFFFFFFFF node

バリアントフィールドには、のレイアウトを識別する値が含まれていますUUID。上記のビットレイアウトは、 Leach-SalzUUIDバリアントを示すバリアント値が2のaに対してのみ有効です。

バージョンフィールドは、このタイプを説明する値を保持しますUUID。UUIDには、時間ベース、DCEセキュリティ、名前ベース、およびランダムに生成されたUUIDの4つの異なる基本タイプがあります。これらのタイプのバージョン値は、それぞれ1、2、3、および4です。

于 2012-08-06T03:19:17.267 に答える