Dart 中的 stdout.write() 显然已从同步更改为异步,但我该如何使用它呢?

Posted

技术标签:

【中文标题】Dart 中的 stdout.write() 显然已从同步更改为异步,但我该如何使用它呢?【英文标题】:stdout.write() in Dart has apparently been altered from sync to async, but how can I use it? 【发布时间】:2013-10-19 09:23:25 【问题描述】:

我在 Dart 的许多地方都使用了 stdout.write(),以免换行。它工作正常,但最近已从同步更改为异步。我刚刚在 Win7-32​​ 和 Win8-64 上升级到 Dart 28355。

以下描述变化:

“有什么变化? 在所有平台上,对 stdout 和 stderr 的写入曾经是阻塞的。作为清理的一部分,这现在与 dart:io 中的任何其他流一样是异步/非阻塞的。 如何更新我的代码? 大多数代码应该像以前一样工作,除了调用 'exit' 时的少数情况:"

我想实现的一个小例子如下:

import 'dart:io';

main() 
  String sCorrectYn;
  while (sCorrectYn != "y") 
    String sName = fInputString("Enter Name : ");     
    sCorrectYn = fInputString("Details Correct? (y/n) : ");
  


String fInputString(String sPrompt) 
  stdout.write("\n$sPrompt");
  return stdin.readLineSync().toLowerCase();

上面在win8上运行时的终端输出如下:

c:\Users\boh\dart-dev1\testpg001>dart testinput001.dart

Enter Name : abcd
n
xxxx
n
zzzz
y

Details Correct? (y/n) :
Enter Name :
Details Correct? (y/n) :
Enter Name :
Details Correct? (y/n) :
c:\Users\boh\dart-dev1\testpg001>

上面发生的情况是,在我最终输入“y”之后,所有终端输出都出现了,这会终止程序并刷新输出缓冲区(它出现了)。第一个终端输出“输入名称:”是唯一应该出现的输出。

似乎没有标准输出的“刷新”方法。

我曾尝试使用未来的标准输出,但我无法让它正常运行。

我怎样才能让它以所需的方式工作?

以下使用 stdout.write() 也无法正常工作:

import 'dart:io';

main() 
  String sInput;
  stdout.write("\nEntry 1 : ");
  sInput = stdin.readLineSync();
  print("Date Entered (1) was : $sInput");  
  stdout.write("\nEntry 2 : ");  
  sInput = stdin.readLineSync();
  print("Date Entered (2) was : $sInput");  
  stdout.write("\nEntry 3 : ");
  sInput = stdin.readLineSync();
  print("Date Entered (3) was : $sInput");  
  stdout.write("\nEntry 4 : ");
  sInput = stdin.readLineSync();
  print("Date Entered (4) was : $sInput");   
  stdout.write("\nEntry 5 : ");
  sInput = stdin.readLineSync();
  print("Date Entered (5) was : $sInput");   

上面的终端显示显示第一行“Entry 1:”仅在使用 stdout.write() 时需要显示的行:

c:\Users\boh\dart-dev1\testpg001>dart testinput003.dart

Entry 1 : aaa
Date Entered (1) was : aaa
bbb
Date Entered (2) was : bbb
ccc
Date Entered (3) was : ccc
ddd
Date Entered (4) was : ddd
eee
Date Entered (5) was : eee

Entry 2 :
Entry 3 :
Entry 4 :
Entry 5 :
c:\Users\boh\dart-dev1\testpg001>

【问题讨论】:

您的 while 循环正在阻止任何异步事件的发生。在这种情况下,你真的需要切换到未来。请展示您对期货的尝试。 我试过不循环,结果是一样的。除了第一行,stdout.write() 没有输出,直到程序终止。我对未来没有运气,我不知道那里是否有解决方案,对我来说似乎没有。如果有人可以说明如何使其工作,我将不胜感激,因为我需要它与输入一起工作(readLineSync())。我需要处理对提示的连续响应的输入。 【参考方案1】:

“刷新”iosink 的功能可以通过使用StreamController 创建一个可以等待的新Stream 来实现。我已经使用 writeAndFlush 辅助方法重写了您上面的示例。

import 'dart:async';
import 'dart:convert';
import 'dart:io';

main() 
  void loop() 
    fInputString("Enter Name : ")
      .then((_) => fInputString("Details Correct? (y/n) : "))
      .then((sCorrectYn) 
        if (sCorrectYn != "y") loop();
      );
  
  loop();


Future<String> fInputString(String sPrompt) 
  return writeAndFlush(stdout, "\n$sPrompt")
    .then((_) 
      return stdin.readLineSync().toLowerCase();
    );


Future writeAndFlush(IOSink sink, object) 
  return sink.addStream(
    (new StreamController()
      ..add(UTF8.encode(object.toString()))
      ..close())
      .stream);

向 IOSink 添加一个flush,这正是我们应该考虑的一个选项。

请注意,这实际上不是 IO 级别的“刷新”,而是等待Stream 被读取结束,即等待Stream 可能被操作系统暂停和恢复.

【讨论】:

这是我看到的,如果我错了,请纠正我。虽然这个答案解决了基本问题并且很容易在一个小型测试程序中实现,但它把我的同步程序变成了一个异步程序(终端输入),这又使它变得复杂了。过去,该程序使用异步输入。然后从内存中引入了readByteSync(),然后是readLineSync()。这使程序能够同步,从而简化了它。要将其改回异步,我相信说明了不输出换行符的终端需要同步写入。 。已经有同步的“打印”语句,但它输出一个换行符,在提示输入时不需要它。在我看来,虽然我认为异步写入是可取的,但同步写入也是如此,我们现在有一个同步读取,但没有换行符的同步写入。我不在乎它叫什么,但我认为我需要它(同步写入到控制台而不使用换行符)。

以上是关于Dart 中的 stdout.write() 显然已从同步更改为异步,但我该如何使用它呢?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 sys.stdout.write 被调用两次?

sys.stdout.write 和 print 的区别?

[Python]sys.stdin.readline(), sys.stdout.write(), sys.stdin.write()

python中print(obj) 与sys.stdout.write()的区别

我无法使用 stdout.write 打印到 VSCode 的控制台

python unicode处理print和sys.stdout.write之间的差异