Concatenating files

Let's suppose that we have a number of text files we want to glue together in one big file. This recipe with code in the project concat_files shows you how this can be done.

How to do it...

The program is launched from the command line in the bin folder (or in Dart Editor with a Managed Launch with Script arguments file1.txt file2.txt file.txt) as dart co ncat.dart file1.txt file2.txt file.txt, where file1.txt and file2.txt are the files to be concatenated (there can be two or more files) into file.txt. The following is the code to perform this:

import 'dart:io';
import 'package:args/args.dart';

ArgResults argResults;
File output;

void main(List<String> arguments) {
  final parser = new ArgParser();
  argResults = parser.parse(arguments);
  final outFile = argResults.rest.last;
  List<String> files = argResults.rest.sublist(0, argResults.rest.length - 1);
  if (files.isEmpty) {
    print('No files provided to concatenate!'),
    exit(1);
  }
output = new File(outFile);
if (output.existsSync()) {
  output.delete();
  }
  concat(files);
  }

concat(List<String> files) {
  for (var file in files) {
  var input = new File(file);
  try {
    var content = input.readAsStringSync();
    content += "
";
    output.writeAsStringSync(content, mode: FileMode.APPEND);
    } catch (e) {
    print("An error $e occurred");
    }
  }
}

How it works...

We use the args package to get the output file name and the files to concatenate. To start with an empty output file, we delete it when it already exists. Then, we loop over all the input files, successively reading an input file and write it to the output in the append mode. We do all these operations in the synchronous mode, because we don't want the content of the files to be mingled.

There's more...

In concat2.dart, which you can find within the concat_files folder, we see an asynchronous version that also works here—only the code in the concat method has to change. Have a look at the following code:

IOSink snk;

Future concat(List<String> files) {
snk = output.openWrite(mode: FileMode.APPEND);
  return Future.forEach(files, (file) {
    Stream<List<int>> stream = new File(file).openRead();
    return stream.transform(UTF8.decoder)
    .transform(const LineSplitter())
    .listen((line) {
    snk.write(line + "
");
    }).asFuture().catchError((_) => _handleError(file));
  });
}

_handleError(String file) {
  FileSystemEntity.isDirectory(file).then((isDir) {
  if (isDir) {
    print('error: $file is a directory'),
    } else {
    print('error: $file not found'),
    }
  });
}

We write to an IOSink object snk using the openWrite method in the append mode. The Future.forEach method asynchronously runs the callback provided on each file. The forEach method runs the callback for each element in order, moving to the next element only when the Future returned by the callback completes. The stream is transformed; transformers are used here to convert the data to UTF-8 and split string values into individual lines.

See also

  • Refer to the Parsing command-line arguments recipe, Chapter 2, Structuring, Testing, and Deploying an Application, for more information on using the args package, and the Transforming streams recipe in this chapter.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset