0

在等待Future<Map<String, T>>之后加载资产非常容易。将文件嵌入程序代码中更加容易。

import 'dart:convert' as JSON;

void main() {
  var jsonStr = """{ "en": "Greetings, World!", "cn": "你好,世界!" }""";

  final json = JSON.jsonDecode(jsonStr);
  print(json.length);
}

但是假设我压缩和uuencode file.json.gz file.json.gz上面的 JSON 字符串,获得:

begin 644 file.json.gz
M'XL("#1&\F```V9I;&4N:G-O;@"K5E!*S5.R4E!R+TI-+<G,2R_640C/+\I)
G453245!*!DL]V;O@Z=*][_?T/-DQ[?G4'D4EA5HN`+"N/9PX````
`
end

然后将结果嵌入代码中:

import 'dart:convert' as JSON;

void main() {
  var str = """    M'XL("#1&\F```V9I;&4N:G-O;@"K5E!*S5.R4E!R+TI-+<G,2R_640C/+\I)
G453245!*!DL]V;O@Z=*][_?T/-DQ[?G4'D4EA5HN`+"N/9PX````
`""";

  ...    
}

我如何对 Dart 中的 uuencoded 字符串进行 uudecode?

现代化到 base64

正如 jamesdlin 非常详细的答案所暗示的那样(尽管答案处理uuencode),使用 base64 是优越的,并且仍然可以通过uuencode使用-mswitch 来获得。

> uuencode -m file.json.gz file.json.gz
begin-base64 644 file.json.gz
H4sICH6y8mAAA2ZpbGUuanNvbgCrVlBKzVOyUlByL0pNLcnMSy/WUQjPL8pJUVTSUVBKBks92bvg
6dK97/f0PNkx7fnUHkUlhVouALCuPZw4AAAA
====

在这种情况下,我们可以使用base64Decodefrom dart:convert

void main() {
  var str = """begin-base64 644 file.json.gz
H4sICH6y8mAAA2ZpbGUuanNvbgCrVlBKzVOyUlByL0pNLcnMSy/WUQjPL8pJUVTSUVBKBks92bvg
6dK97/f0PNkx7fnUHkUlhVouALCuPZw4AAAA
====""";

  ...    
}
4

1 回答 1

1

我根据Wikipedia 对 uuencode scheme 的描述编写了一个粗略的 uudecode 实现。请注意,下面的代码没有经过很好的测试,它只是对文件内容进行解码;如果您想使用原始文件名和权限将文件写入存储,这留给读者作为练习。

import 'dart:typed_data';

Uint8List uudecode(String uuencoded) {
  var lines = uuencoded.trim().split('\n');
  if (lines.length < 3) {
    throw FormatException('Missing preamble and/or postamble.');
  }

  // This ignores the header.

  // Since the input is expected to be a uuencoded string, its code units
  // should be ASCII values.
  var decodedBytes = <int>[];
  for (var line in lines.skip(1)) {
    var data = [for (var codeUnit in line.codeUnits) codeUnit - 32];
    if (data.isEmpty) {
      throw FormatException('Missing length byte.');
    }

    if ((data.length - 1) % 4 != 0) {
      throw FormatException('Encoded data length is not a multiple of 4.');
    }

    var decodedLineLength = data[0];
    if (decodedLineLength >= 64) {
      break;
    }

    // Explicitly restrict each element to 6-bits since the uuencode
    // implementation from GNU sharutils encodes NUL bytes as `.
    for (var i = 1; i < line.codeUnits.length; i += 1) {
      data[i] &= 0x3F;
    }

    var decodedLineBytes = <int>[];
    var i = 1;
    while (true) {
      // Combine the next 4 elements into a 24-bit value.
      var concatenated = 0;
      concatenated |= data[i++] << 18;
      concatenated |= data[i++] << 12;
      concatenated |= data[i++] << 6;
      concatenated |= data[i++];

      // Extract 3 bytes from the 24-bit value.
      decodedLineBytes.add((concatenated >> 16) & 0xFF);
      decodedLineBytes.add((concatenated >> 8) & 0xFF);
      decodedLineBytes.add(concatenated & 0xFF);
      if (decodedLineBytes.length >= decodedLineLength) {
        // Remove padding bytes.
        decodedBytes.addAll(decodedLineBytes.getRange(0, decodedLineLength));
        break;
      }
    }
  }
  return Uint8List.fromList(decodedBytes);
}

void main() {
  var uuencoded = r'''\
begin 644 wikipedia-url.txt
::'1T<#HO+W=W=RYW:6MI<&5D:6$N;W)G#0H`
`
end
''';
  
  var decoded = uudecode(uuencoded);
  print('${decoded.length}: $decoded');
  print('${String.fromCharCodes(decoded)}'); // Prints: http://www.wikipedia.org
}

综上所述,除非你有一些外部要求迫使你使用 uuencode,否则我建议使用 base64 代替,因为它的编码大小略小,现在更常见,而且 Dart SDK 直接包含base64 支持

于 2021-07-17T05:31:09.407 回答