我如何在 Dart 中进行 uudecode?

How can I uudecode in Dart?

之后为 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 的使用更优越,并且仍然可以使用 [=19= 从 uuencode 获得]开关。

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

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

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

  ...    
}

我基于 Wikipedia's description for the uuencode scheme 编写了一个粗略的 uudecode 实现。请注意,以下代码未经过充分测试,它只是对文件内容进行解码;如果您想使用原始文件名和权限将文件写入存储,则留作 reader.

的练习。
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,因为它的编码大小稍小,it's far more common nowadays, and since the Dart SDK directly includes base64 support