ZetCode

Dart WritePipe

last modified October 18, 2026

The WritePipe interface in Dart represents the writable end of an anonymous operating system pipe. It is part of the dart:io library and shares the familiar IOSink API used by files and sockets.

A WritePipe is not created directly. You obtain one from Pipe.create().write or by extracting it from a ResourceHandle with toWritePipe.

Basic Definition

WritePipe is an abstract interface class that implements IOSink. It provides write, writeln, add, addStream, flush, and close.

Text written to a WritePipe is encoded using the sink's encoding, which defaults to UTF-8. Byte lists are written unchanged.

Basic WritePipe Usage

This example writes text to a pipe and reads it back from the other end.

main.dart
import 'dart:convert';
import 'dart:io';

Future<void> main() async {
  var pipe = await Pipe.create();
  var result = pipe.read.transform(utf8.decoder).join();

  var writePipe = pipe.write;
  writePipe.write('Hello, World!');
  await writePipe.close();

  print(await result);
}

We obtain the write end from pipe.write, write a string, and close it so the reader sees end-of-file. The result confirms that the bytes arrived intact.

$ dart main.dart
Hello, World!

Writing Multiple Chunks

This example demonstrates writing data in multiple chunks using a WritePipe.

main.dart
import 'dart:convert';
import 'dart:io';

Future<void> main() async {
  var pipe = await Pipe.create();
  var result = pipe.read.transform(utf8.decoder).join();
  var writePipe = pipe.write;

  for (var i = 0; i < 5; i++) {
    writePipe.writeln('Chunk $i');
    print('Wrote chunk $i');
  }

  await writePipe.close();
  print('All chunks written');
  print(await result);
}

Each writeln appends the text and a newline. Closing the write end flushes the buffered data. The reader then receives all five lines as one stream.

$ dart main.dart
Wrote chunk 0
Wrote chunk 1
Wrote chunk 2
Wrote chunk 3
Wrote chunk 4
All chunks written
Chunk 0
Chunk 1
Chunk 2
Chunk 3
Chunk 4

Error Handling

This example shows the error produced when writing to a closed pipe.

main.dart
import 'dart:io';

Future<void> main() async {
  var pipe = await Pipe.create();
  var writePipe = pipe.write;
  await writePipe.close();

  try {
    writePipe.write('Test data');
    await writePipe.flush();
  } catch (e) {
    print('Error occurred: $e');
  }
}

Once a WritePipe is closed, further writes throw a StateError. Catch and handle this error if the writer's lifetime is not fully controlled.

$ dart main.dart
Error occurred: Bad state: StreamSink is closed

Writing Binary Data

This example demonstrates writing binary data through a WritePipe.

main.dart
import 'dart:io';
import 'dart:typed_data';

Future<void> main() async {
  var pipe = await Pipe.create();
  var result = pipe.read.expand((chunk) => chunk).toList();
  var writePipe = pipe.write;

  var data = Uint8List.fromList([0, 1, 2, 3, 4, 5]);
  writePipe.add(data);
  await writePipe.close();

  print('Binary data written: ${await result}');
}

add writes a byte list without text encoding. Reading the other end with expand produces the original byte sequence.

$ dart main.dart
Binary data written: [0, 1, 2, 3, 4, 5]

Writing to a Socket

A network socket is also an IOSink, so it uses the same writing methods as a WritePipe. This example sends an HTTP request to a local server and reads it back.

main.dart
import 'dart:io';

Future<void> main() async {
  var server = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);

  var received = server.first.then((socket) async {
    var bytes = await socket.expand((chunk) => chunk).toList();
    await socket.close();
    return String.fromCharCodes(bytes);
  });

  var client = await Socket.connect(InternetAddress.loopbackIPv4, server.port);
  client.write('GET / HTTP/1.1\r\n');
  client.write('Host: localhost\r\n');
  client.write('Connection: close\r\n\r\n');
  await client.close();
  client.destroy();

  print('Received by server:');
  print((await received).trim());

  await server.close();
}

The socket's write and close methods come from IOSink. After closing the sending side, destroy releases the client socket completely. The server drains its accepted socket, closes it, and returns the received request text.

$ dart main.dart
Received by server:
GET / HTTP/1.1
Host: localhost
Connection: close

Best Practices

Source

Dart WritePipe Documentation

This tutorial covered Dart's WritePipe interface with practical examples showing text writing, multiple chunks, errors, binary data, and socket output.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Dart tutorials.