tar 0.4.0 tar: ^0.4.0 copied to clipboard
Memory-efficient, streaming implementation of the tar file format
tar #
This package provides stream-based readers and writers for tar files.
When working with large tar files, this library consumes considerably less memory than package:archive, although it is slightly slower.
Reading #
To read entries from a tar file, use
import 'dart:convert';
import 'dart:io';
import 'package:tar/tar.dart';
Future<void> main() async {
final reader = TarReader(File('file.tar').openRead());
while (await reader.moveNext()) {
final entry = reader.current;
// Use reader.header to see the header of the current tar entry
print(entry.header.name);
// And reader.contents to read the content of the current entry as a stream
print(await entry.contents.transform(utf8.decoder).first);
}
// Note that the reader will automatically close if moveNext() returns false or
// throws. If you want to close a tar stream before that happens, use
// reader.cancel();
}
To read .tar.gz
files, transform the stream with gzip.decoder
before
passing it to the TarReader
.
To easily go through all entries in a tar file, use TarReader.forEach
:
Future<void> main() async {
final inputStream = File('file.tar').openRead();
await TarReader.forEach(inputStream, (entry) {
print(header.name);
print(await entry.contents.transform(utf8.decoder).first);
});
}
Warning: Since the reader is backed by a single stream, concurrent calls to
read
are not allowed! Similarly, if you're reading from an entry's contents
,
make sure to fully drain the stream before calling read()
again.
Writing #
You can write tar files into a StreamSink<List<int>>
, such as an IOSink
:
import 'dart:convert';
import 'dart:io';
import 'package:tar/tar.dart';
Future<void> main() async {
final output = File('test.tar').openWrite();
await Stream<TarEntry>.value(
TarEntry.data(
TarHeader(
name: 'hello.txt',
mode: int.parse('644', radix: 8),
),
utf8.encode('Hello world'),
),
).pipe(tarWritingSink(output));
}
To write .tar.gz
files, you can again transform the stream twice:
import 'dart:io';
import 'package:tar/tar.dart';
Future<void> write(Stream<TarEntry> entries) {
return entries
.transform(tarWriter)
.transform(gzip.encoder)
.pipe(File('output.tar.gz').openWrite());
}
Note that, by default, tar files are written in the pax format defined by the
POSIX.1-2001 specification (--format=posix
in GNU tar).
When all entries have file names shorter than 100 chars and a size smaller
than 8 GB, this is equivalent to the ustar
format. This library won't write
PAX headers when there is no reason to do so.
If you prefer writing GNU-style long filenames instead, you can use the
format
option:
Future<void> write(Stream<TarEntry> entries) {
return entries
.transform(tarWriterWith(format: OutputFormat.gnuLongName))
.pipe(tarWritingSink(
File('output.tar.gz').openWrite(),
format: OutputFormat.gnuLongName,
));
}
Features #
- Supports v7, ustar, pax, gnu and star archives
- Supports extended pax headers for long file or link names
- Supports long file and link names generated by GNU-tar
- Hardened against denial-of-service attacks with invalid tar files
Big thanks to Garett Tok Ern Liang for writing the initial Dart tar reader that this library is based on.