【问题标题】:How do I capture stdin (more than one line) to a String in Dart?如何将标准输入(多行)捕获到 Dart 中的字符串?
【发布时间】:2015-03-01 05:02:09
【问题描述】:

我有一个 Dart 命令行程序,它希望能够将数据从 shell 传送到 Dart 程序(例如,cat file.txt | dart my_program.dart 或接受输入,直到用户使用 Ctrl+d)。通过在线教程,我发现从标准输入保存输入的唯一文档是stdin.readLineSync()。但是,顾名思义,这只读取第一行。

如何才能将标准输入的全部内容捕获到一个字符串中?此外,如果用户试图通过管道输入一个非常大的文件,是否会有任何安全问题?字符串的长度是否有限制?我该如何防范呢?

感谢您的帮助!

【问题讨论】:

    标签: dart dart-io


    【解决方案1】:

    如果以交互方式使用以下程序,将回显您的输入,但将每个字符大写。

    您也可以通过管道向它发送文件。

    dart upper_cat.dart < file.txt
    

    这将输出每个字符大写的文件。

    import 'dart:convert';
    import 'dart:io';
    
    main() {
    
      // Stop your keystrokes being printed automatically.
      stdin.echoMode = false;
    
      // This will cause the stdin stream to provide the input as soon as it
      // arrives, so in interactive mode this will be one key press at a time.
      stdin.lineMode = false;
    
      var subscription;
      subscription = stdin.listen((List<int> data) {
    
        // Ctrl-D in the terminal sends an ascii end of transmission character.
        // http://www.asciitable.com/
        if (data.contains(4)) {
          // On my computer (linux) if you don't switch this back on the console
          // will do wierd things.
          stdin.echoMode = true;
    
          // Stop listening.
          subscription.cancel();
        } else {
    
          // Translate character codes into a string.
          var s = LATIN1.decode(data);
    
          // Capitalise the input and write it back to the screen.
          stdout.write(s.toUpperCase());
        }
      });
    
    }
    

    还有console 库可以帮助解决这类问题。我还没有尝试过,但试一试并报告;)

    以下示例处理 UTF8 输入 - 上面的示例需要 1 字节字符作为输入。

    import 'dart:convert';
    import 'dart:io';
    
    main() {
    
      stdin.echoMode = false;
      stdin.lineMode = false;
    
      var subscription;
      subscription = stdin
        .map((List<int> data) {
          if (data.contains(4)) {
            stdin.echoMode = true;
            subscription.cancel();
          }
          return data;
        })
        .transform(UTF8.decoder)
        .map((String s) => s.toUpperCase())
        .listen(stdout.write);
    }
    

    【讨论】:

    • 你好,格雷格!谢谢你的建议。我不太清楚如何修改您的代码以满足我的需要。请参阅我对 Günter 解决方案的评论。基本上,我正在尝试做类似String input = stdin.readLineSync() 的事情,但能够保存多行而不是只保存一行。如果您有任何其他建议,请告诉我!谢谢!
    • 我认为您需要更清楚地了解您要解决的问题。即一个函数可以监听输入并在 Ctrl+D 到达时返回一个字符串。或者程序可以等待换行符并返回包含该行的字符串。如果一个程序应该读取多行,它怎么知道它已经读完了?它会等到它读取一个空行吗?还是会等到它读到一行带有“end”字样的行?
    【解决方案2】:

    我研究了stdin.readLineSync() 的代码并能够修改它以满足我的需要:

    import 'dart:convert';
    import 'dart:io';
    
    String readInputSync({Encoding encoding: SYSTEM_ENCODING}) {
      final List input = [];
      while (true) {
        int byte = stdin.readByteSync();
        if (byte < 0) {
          if (input.isEmpty) return null;
          break;
        }
        input.add(byte);
      }
      return encoding.decode(input);
    }
    
    void main() {
      String input = readInputSync();
      myFunction(input); // Take the input as an argument to a function
    }
    

    我需要从标准输入同步读取以暂停程序,直到读取整个标准输入(直到文件结尾或 Ctrl+d)。

    感谢您的所有帮助!如果没有你的帮助,我想我无法弄清楚。

    【讨论】:

      【解决方案3】:

      你可以使用

      import 'dart:io' as io;
      import 'dart:async' show Future, Stream, StreamSubscription;
      import 'dart:convert' show UTF8;
      
      void main() {
        StreamSubscription subscr = io.stdin.transform(UTF8.decoder).listen((data) => 
            print(data));
      }
      

      您可以控制是否应该接收更多数据

      subscr.pause();
      subscr.resume();
      

      如果我没记错的话,在标准输入上侦听以 16kb 的块传递数据(由 Dart 定义的 io 缓冲区大小)这允许您接收可以处理的数据量。 如果你想在内存中保留一个大字符串,你需要有可用的内存。

      另见
      - https://stackoverflow.com/a/26343041/217408(设置虚拟机内存)
      - https://stackoverflow.com/a/12691502/217408
      - https://stackoverflow.com/a/28039661/217408

      【讨论】:

      • 谢谢,君特。我尝试了你的建议,但我仍然不确定这如何将标准输入捕获到 Dart 中的字符串。您能否进一步扩展您的答案?再次感谢!
      • 我更新了我的答案。如果您想要更具体的答案,请提供更多信息,说明您尝试完成的工作以及究竟是什么导致您遇到麻烦。
      • 嘿,君特。抱歉,我迟到了。您的建议有效,但我无法对其进行修改以满足我的需要。基本上,我正在尝试做类似String input = stdin.readLineSync() 的事情,但能够保存多行而不是只保存一行。作为背景,我正在开发一个 CSS 预处理器。所以我需要将标准输入保存到一个字符串中,然后处理这个字符串。
      猜你喜欢
      • 1970-01-01
      • 2021-10-20
      • 1970-01-01
      • 2020-08-03
      • 2011-03-05
      • 2021-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多