Dart StdioType
last modified May 28, 2026
The StdioType enum in Dart identifies the type of standard IO
streams. The top-level stdioType function from dart:io
takes a stream or sink as an argument and returns a StdioType value
indicating whether it is a terminal, pipe, file, or other type of stream.
stdioType is part of Dart's dart:io library and is
particularly useful when working with process communication or when you need
to adjust behavior based on the IO stream type.
Basic Definition
StdioType is an enumeration that identifies different types of
standard IO streams. It helps determine how to handle various IO operations.
The class provides constants like TERMINAL, PIPE,
FILE, and OTHER to classify standard streams.
It's often used with stdin, stdout, and stderr.
Checking stdin Type
This example shows how to check the type of the standard input stream.
import 'dart:io';
void main() {
var stdinType = stdioType(stdin);
if (stdinType == StdioType.terminal) {
print('Input is from a terminal');
} else if (stdinType == StdioType.pipe) {
print('Input is from a pipe');
} else {
print('Input is of type: $stdinType');
}
}
We pass stdin to the top-level stdioType function to
determine its type. This helps establish whether the program is receiving input
interactively or through a pipe.
$ dart main.dart Input is from a terminal $ echo "test" | dart main.dart Input is from a pipe
Detecting Output Stream Type
This example demonstrates checking the type of standard output streams.
import 'dart:io';
void main() {
checkStreamType(stdout, 'stdout');
checkStreamType(stderr, 'stderr');
}
void checkStreamType(IOSink stream, String name) {
var type = stdioType(stream);
print('$name type: $type');
print('Is terminal: ${type == StdioType.terminal}');
}
We examine both stdout and stderr streams to determine their types. This can be useful for formatting output differently based on destination.
$ dart test.dart stdout type: StdioType: terminal Is terminal: true stderr type: StdioType: terminal Is terminal: true
Handling Different Stream Types
This example shows how to adjust behavior based on the stream type.
import 'dart:io';
void main() {
var output = stdout;
switch (stdioType(output)) {
case StdioType.terminal:
output.writeln('Writing to terminal - adding colors');
break;
case StdioType.pipe:
output.writeln('Writing to pipe - plain output');
break;
case StdioType.file:
output.writeln('Writing to file - no terminal features');
break;
default:
output.writeln('Writing to unknown stream type');
}
}
We use a switch statement to handle different output stream types differently. This pattern is common for CLI tools that adapt to their environment.
$ dart main.dart Writing to terminal - adding colors $ dart main.dart | cat Writing to pipe - plain output
Checking File Descriptors
This example demonstrates checking StdioType for arbitrary file descriptors.
import 'dart:io';
void main() async {
var file = File('test.txt');
var sink = file.openWrite();
print('File stream type: ${stdioType(sink)}');
await sink.close();
var socket = await Socket.connect('google.com', 80);
print('Socket stream type: ${stdioType(socket)}');
socket.destroy();
}
We pass different IO objects to the top-level stdioType function.
For objects that are not standard streams (such as a file sink or socket),
it returns StdioType.other.
$ dart main.dart File stream type: StdioType.FILE Socket stream type: StdioType.OTHER
Process Communication with StdioType
This example shows using StdioType in process communication scenarios.
import 'dart:convert';
import 'dart:io';
void main() async {
var process = await Process.start('ls', ['-l']);
print('Process stdin type: ${stdioType(process.stdin)}');
print('Process stdout type: ${stdioType(process.stdout)}');
print('Process stderr type: ${stdioType(process.stderr)}');
print('process output lines:');
process.stdout
.transform(SystemEncoding().decoder)
.transform(const LineSplitter())
.listen(print);
await process.exitCode;
}
When spawning processes, StdioType helps determine how to handle
the process streams. This is useful for building process management tools.
Inspecting Subprocess Streams
The next example shows how StdioType can be used in a more
practical setting. Instead of inspecting only the current process, we launch
external commands, capture their output, and report the stream types associated
with each subprocess. The helper function runAndInspect
encapsulates this workflow so the program can start a command, print the
StdioType values for its streams, drain the output safely, and
return the collected data for further use.
import 'dart:convert';
import 'dart:io';
/// Runs a subprocess and reports its StdioType for stdin/stdout/stderr,
/// then collects and returns all stdout lines.
Future<List<String>> runAndInspect(String cmd, List<String> args) async {
final process = await Process.start(cmd, args);
final label = '[$cmd ${args.join(" ")}]';
print('$label stdin : ${stdioType(process.stdin)}');
print('$label stdout: ${stdioType(process.stdout)}');
print('$label stderr: ${stdioType(process.stderr)}');
// Capture stdout lines while draining stderr so the process never blocks.
final lines = <String>[];
final decoder = SystemEncoding().decoder;
final stdoutDone = process.stdout
.transform(decoder)
.transform(const LineSplitter())
.forEach((line) => lines.add(line));
final stderrDone = process.stderr
.transform(decoder)
.transform(const LineSplitter())
.forEach((line) => stderr.writeln('[stderr] $line'));
await Future.wait([stdoutDone, stderrDone]);
await process.exitCode;
return lines;
}
void main(List<String> argv) async {
final dir = argv.isNotEmpty ? argv[0] : '.';
// ── 1. List files ────────────────────────────────────────────────────────
print('\n=== ls: list files in "$dir" ===');
final entries = await runAndInspect('ls', ['-1', dir]);
print('Found ${entries.length} entries\n');
// ── 2. Count lines in each file ───────────────────────────────────────────
final files = entries
.map((e) => '$dir/$e')
.where((p) => File(p).existsSync())
.toList();
if (files.isNotEmpty) {
print('=== wc: count lines ===');
final counts = await runAndInspect('wc', ['-l', ...files]);
counts.forEach(print);
print('');
}
// ── 3. Detect file types ──────────────────────────────────────────────────
if (files.isNotEmpty) {
print('=== file: detect MIME types ===');
final types = await runAndInspect('file', ['--mime-type', ...files]);
types.forEach(print);
print('');
}
// ── 4. Compare against our own stdio ─────────────────────────────────────
print('=== this process own stdio ===');
print('stdin : ${stdioType(stdin)}');
print('stdout: ${stdioType(stdout)}');
print('stderr: ${stdioType(stderr)}');
}
This example demonstrates how stream-type inspection fits naturally into larger process-handling tasks. By checking the StdioType of each stream, the program can adjust its behavior depending on whether it is connected to a terminal or a pipe. The structure also highlights a clean way to manage subprocess output without blocking, while keeping the logic reusable for any command the program needs to run.
┌──────────────────────────────┐
│ Your Terminal │
│ (keyboard + screen + TTY) │
└──────────────┬───────────────┘
│
│ real terminal
│
┌──────────▼─────────-─┐
│ Dart Program │
│ (first.dart) │
├──────────────────────┤
│ stdin : terminal │
│ stdout : terminal │
│ stderr : terminal │
└───────┬─────┬────────┘
│ │
│ │ creates pipes
│ │
┌───────────────────┘ └─────────-──────────┐
│ │
┌───────▼───────-─┐ ┌────────▼─────-──┐
│ Child Proc │ │ Child Proc │
│ ls │ │ wc │
├─────────────────┤ ├─────────────────┤
│ stdin : other │ │ stdin : other │
│ stdout : pipe │ │ stdout : pipe │
│ stderr : pipe │ │ stderr : pipe │
└───────┬─────────┘ └────────┬────────┘
│ │
│ pipes (not a terminal) │
│ │
└──────────────────────────────────────────────┘
This diagram shows how the program's own standard streams are connected to the terminal, while the child processes' streams are connected via pipes.
Best Practices
- Check early: Verify stream types at program start
- Adapt output: Adjust formatting based on stream type
- Handle other: Provide default behavior when
stdioTypereturnsStdioType.other - Fallback: Provide default behavior for other type
Source
This tutorial covered Dart's StdioType class with practical examples showing how to identify and handle different standard IO stream types in Dart.
Author
List all Dart tutorials.