如何在Dart中生成唯一标识符

141

我正在编写 WebSocket 聊天功能。如何为用户生成唯一的 ID?

目前我使用的是以下代码:

id = new DateTime.now().millisecondsSinceEpoch;

还有更简便的解决方案吗?

8个回答

201

1. 有一个 UUID 发布包:

http://pub.dartlang.org/packages/uuid

用法示例:

import 'package:uuid/uuid.dart';

// Create uuid object
var uuid = Uuid();

// Generate a v1 (time-based) id
uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'

// Generate a v4 (random) id
uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'

// Generate a v5 (namespace-name-sha1-based) id
uuid.v5(uuid.NAMESPACE_URL, 'www.google.com'); // -> 'c74a196f-f19d-5ea9-bffd-a2742432fc9c'

2. 这个src包含一个Dart GUID生成器

https://github.com/MikeMitterer/AndroidIconGenerator.DART/blob/445884924/lib/src/model/communication/GUIDGen.dart

我不会直接在这里发布函数src,因为它没有明显的许可证,但是下面是它的使用示例:

final String uuid = GUIDGen.generate();

22
小心提醒:这不依赖于强随机数据,因此生成的 UUID 不应被视为具有密码学强度。它是否重要,我将留给读者决定。 - Kai Sellgren
谢谢,我知道了。我会再检查一下现有UUID列表。 - Sergey Karasev
1
@KaiSellgren 这是一篇相当旧的帖子,但我认为通过在这里提问,我可以丰富它。你说“这不依赖于强随机数据”。你能详细说明一下吗?我的意思是,我们如何使它更强大? - Felipe
1
@Felipe,该库现在似乎有一种替代方法用于生成随机数据:https://github.com/Daegalus/dart-uuid/blob/master/lib/uuid_util.dart -- 我尚未验证或测试其强度,但你可以通过计算卡方分布来轻松地完成。如果您感到好奇,我的Github页面上有一个项目用于确定随机数据的强度。 - Kai Sellgren
如何从字符串创建对象?当您使用数据库传输对象时,需要考虑这一点。 - withoutOne
显示剩余2条评论

79

32
我认为这个类的设计初衷是用于小部件,而不是作为数据库中的ID使用。 - Gino
11
如果你查看这个类,你会清楚地看到它创建的键仅在应用程序内是唯一的。这意味着如果你将键保存在应用程序外部比如数据库中,以后可能会重新创建相同的唯一键。请参考此处链接,从第83行到103行,还有一些讨论供你参考。 - Gino
1
谢谢你,吉诺。但对我来说,16^5已经足够随机了。这个UnikeKey()对我的实用程序很有效。当然,它并不是加密安全的,但它是一种快速且内置的方法。 - Rutrus
2
@Rufus,这与加密无关,但如果它对你的实用性有帮助,那么你应该使用它。就像他们说的:“如果它有效,就不要碰它!” - Gino
2
@Gino,你可以使用 UniqueKey().toString() 来获取一个唯一的字符串字面量,该字符串可以保存在数据库中。Flutter团队已经重写了UniqueKey类的toString()方法,以返回与该键相关联的基础ID,请在此处查看 - Son Nguyen
显示剩余7条评论

22

我使用微秒而不是毫秒,这样更准确,而且无需添加任何软件包。

 String idGenerator() {
    final now = DateTime.now();
    return now.microsecondsSinceEpoch.toString();
  }

1
是 - 合理的,且没有依赖关系。 - Kenneth N
我注意到微软总是在后面添加“000”的差异。 - Kucing Malaya
2
对于在Flutter Web上使用此功能的任何人都需要注意:请注意,此值不适合53位(IEEE double的大小)。JavaScript数字无法保存此值。 - Alex Rintt
我在一个Flutter Windows应用程序中遇到了一个情况,当在for循环中使用生成的微秒时(比如连续创建大量记录时),它们会重复多次。请注意,这可能不是一种确保获取唯一值的方法。 - Clifton Labrum

12

如果你使用一个小设备或者批量处理身份证,这是一个非常好的替代方案。 - undefined

4
这个方法可以生成类似于(-N4pvg_50j1CEqSb3SZt)的唯一标识符。
String getCustomUniqueId() {
  const String pushChars =
      '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
  int lastPushTime = 0;
  List lastRandChars = [];
  int now = DateTime.now().millisecondsSinceEpoch;
  bool duplicateTime = (now == lastPushTime);
  lastPushTime = now;
  List timeStampChars = List<String>.filled(8, '0');
  for (int i = 7; i >= 0; i--) {
    timeStampChars[i] = pushChars[now % 64];
    now = (now / 64).floor();
  }
  if (now != 0) {
    print("Id should be unique");
  }
  String uniqueId = timeStampChars.join('');
  if (!duplicateTime) {
    for (int i = 0; i < 12; i++) {
      lastRandChars.add((Random().nextDouble() * 64).floor());
    }
  } else {
    int i = 0;
    for (int i = 11; i >= 0 && lastRandChars[i] == 63; i--) {
      lastRandChars[i] = 0;
    }
    lastRandChars[i]++;
  }
  for (int i = 0; i < 12; i++) {
    uniqueId += pushChars[lastRandChars[i]];
  }
  return uniqueId;
}

3
我已经创建了一个场景来生成唯一的、具有密码学安全性的随机id,其中包括4个随机生成的id:
  1. 从字母表[a-z]中获取前4个字母。

  2. 从数字列表[0-9]中获取中间4位数字。

  3. 获取自纪元以来的微秒数,并截取8到12位,因为它们经常变化。

  4. 从字母表[a-z]中获取后4个字母。

生成的id的屏幕截图如下:

first generated id second generated id third generated id

以下是调用此函数的代码:
  randomIdGenerator() {
  var ranAssets = RanKeyAssets();
  String first4alphabets = '';
  String middle4Digits = '';
  String last4alphabets = '';
  for (int i = 0; i < 4; i++) {
    first4alphabets += ranAssets.smallAlphabets[
        math.Random.secure().nextInt(ranAssets.smallAlphabets.length)];

    middle4Digits +=
        ranAssets.digits[math.Random.secure().nextInt(ranAssets.digits.length)];

    last4alphabets += ranAssets.smallAlphabets[
        math.Random.secure().nextInt(ranAssets.smallAlphabets.length)];
  }

  return '$first4alphabets-$middle4Digits-${DateTime.now().microsecondsSinceEpoch.toString().substring(8, 12)}-$last4alphabets';
}

列表类

    class RanKeyAssets {
  var smallAlphabets = [
    'a',
    'b',
    'c',
    'd',
    'e',
    'f',
    'g',
    'h',
    'i',
    'j',
    'k',
    'l',
    'm',
    'n',
    'o',
    'p',
    'q',
    'r',
    's',
    't',
    'u',
    'v',
    'w',
    'x',
    'y',
    'z'
  ];
  var digits = [
    '0',
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
  ];
}

1

还有https://pub.dev/packages/xid,它是无锁的,并且每秒每个主机/进程保证可生成16777216(24位)个唯一ID。

import 'package:xid/xid.dart';

void main() {
  var xid = Xid();
  print('generated id: $xid');

}


1
如果您喜欢MongoDB风格的ID,您可以考虑使用这个小包来帮助创建对象ID:

https://pub.dev/packages/crossplat_objectid

import 'package:bson_objectid/bson_objectid.dart';

main() {
  ObjectId id1 = new ObjectId();
  print(id1.toHexString());

  ObjectId id2 = new ObjectId.fromHexString('54495ad94c934721ede76d90');
  print(id2.timestamp);
  print(id2.machineId);
  print(id2.processId);
  print(id2.counter);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接