stdin în Dart

stdin este intrarea standard a programului: ce scrie utilizatorul la tastatură sau ce primește programul printr-un pipe.

Sintaxă
import 'dart:io';

Stdin get stdin
// Stdin este un Stream<List<int>> (octeți)

Ce face stdin

Variabila globală stdin din dart:io este un obiect Stdin, adică un Stream<List<int>>: datele vin ca bucăți de octeți. Cel mai des citești câte un rând cu stdin.readLineSync().

Când vrei să prelucrezi toată intrarea (de exemplu un fișier trimis cu dart run main.dart < date.txt sau cat date.txt | dart run main.dart), tratezi stdin ca flux: îl decodifici cu utf8.decoder și îl împarți în rânduri cu LineSplitter.

stdin.hasTerminal spune dacă intrarea vine de la o tastatură (terminal) sau dintr-un fișier/pipe. Fluxul stdin poate fi ascultat o singură dată; după ce l-ai ascultat ca flux, nu mai poți folosi readLineSync.

Exemple

Exemplul 1: Suma notelor primite pe intrare, rând cu rând

Fiecare rând al intrării este o notă. Bucla await for primește rândurile pe măsură ce sosesc.

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

Future<void> main() async {
  final randuri = stdin.transform(utf8.decoder).transform(const LineSplitter());
  var suma = 0;
  var numar = 0;
  await for (final rand in randuri) {
    suma += int.parse(rand);
    numar++;
  }
  print('Note citite: $numar');
  print('Media: ${(suma / numar).toStringAsFixed(2)}');
}

Ce scrie utilizatorul (intrare)

9
10
7
8

Rezultat

Note citite: 4
Media: 8.50

Exemplul 2: Toată intrarea într-un singur String

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

Future<void> main() async {
  final text = await stdin.transform(utf8.decoder).join();
  final cuvinte = text.split(RegExp(r'\s+')).where((c) => c.isNotEmpty);
  print('Caractere: ${text.length}');
  print('Cuvinte: ${cuvinte.length}');
}

Ce scrie utilizatorul (intrare)

Ana are mere.
Ion are pere în Iași.

Rezultat

Caractere: 36
Cuvinte: 8

Exemplul 3: Vine intrarea de la tastatură?

La rularea exemplelor de pe site intrarea vine printr-un pipe, deci hasTerminal este false. Rulat direct în terminal, programul afișează true.

import 'dart:io';

void main() {
  if (stdin.hasTerminal) {
    print('Scrie numele tău și apasă Enter:');
  } else {
    print('Citesc datele dintr-un fișier sau pipe.');
  }
  print('Nume: ${stdin.readLineSync()}');
}

Ce scrie utilizatorul (intrare)

Maria

Rezultat

Citesc datele dintr-un fișier sau pipe.
Nume: Maria

Greșeli frecvente

  • Asculți stdin ca flux și apoi apelezi readLineSync: fluxul a fost deja consumat și primești StateError („Stream has already been listened to”).
  • Uiți utf8.decoder și lucrezi cu liste de octeți: literele românești ocupă câte doi octeți, iar împărțirea pe bucăți le poate tăia la jumătate.

Comenzi înrudite

  • stdin.readLineSync: Citește un rând de la tastatură (intrarea standard) și îl returnează fără Enter; returnează null la sfârșitul intrării.
  • stdin.echoMode: echoMode ascunde sau arată ce tastează utilizatorul (pentru parole); lineMode citește tastele imediat, fără să aștepte Enter.
  • stdout: stdout este ieșirea standard a programului: tot ce apare în terminal; are metodele unui IOSink (write, writeln, writeAll).
  • LineSplitter: Împarte un text în rânduri, recunoscând \n, \r\n și \r; funcționează și pe fluxuri cu transform.
  • utf8.decoder: Convertoarele din spatele lui utf8: decoder transformă fluxuri de octeți în text, encoder face invers.