OLD | NEW |
(Empty) | |
| 1 --- |
| 2 layout: default |
| 3 title: "Write Command-Line Apps" |
| 4 description: "Basics for command-line apps" |
| 5 has-permalinks: true |
| 6 tutorial: |
| 7 id: dart-io |
| 8 next: / |
| 9 next-title: "Home" |
| 10 prev: indexeddb/ |
| 11 prev-title: "Use IndexedDB" |
| 12 --- |
| 13 |
| 14 {% capture whats_the_point %} |
| 15 |
| 16 * Command-line applications need to do input and output. |
| 17 * The dart:io library provides I/O functionality. |
| 18 * The args package helps define and parse command-line arguments. |
| 19 * Most input and output requires the use of Streams. |
| 20 * Streams provide a series of asynchronous data events. |
| 21 * To handle asynchronous data, you need to use Futures. |
| 22 |
| 23 {% endcapture %} |
| 24 |
| 25 {% capture sample_links %} |
| 26 |
| 27 <p> This tutorial features these examples:</p> |
| 28 * helloworld |
| 29 * dcat |
| 30 |
| 31 <p> |
| 32 Don't have the source code? |
| 33 <a href="https://github.com/dart-lang/dart-tutorials-samples/archive/master.zip"
> |
| 34 Download it. |
| 35 </a> |
| 36 |
| 37 {% endcapture %} |
| 38 |
| 39 {% capture content %} |
| 40 |
| 41 <div class="tute-target-title"> |
| 42 <h1>{{page.title}}</h1> |
| 43 <h3>An introduction to standalone apps</h3> |
| 44 </div> |
| 45 |
| 46 This tutorial teaches you how to build command-line apps |
| 47 and shows you a few small command-line applications. |
| 48 These programs use resources that most command-line applications need, |
| 49 including the standard output, error, and input streams, |
| 50 command-line arguments, files and directories, and more. |
| 51 |
| 52 * [Running an app with the standalone Dart VM](#run-the-first-app) |
| 53 * [Review briefly the dcat example code](#dcat-code) |
| 54 * [Parsing command-line arguments](#cmd-line-args) |
| 55 * [Reading and writing with stdin, stdout, and stderr](#std-in-out-err) |
| 56 * [Getting info about a file](#filesystementity) |
| 57 * [Reading a file](#reading-a-file) |
| 58 * [Writing a file](#writing-a-file) |
| 59 * [Getting environment information](#env-var) |
| 60 * [Setting exit codes](#exit-codes) |
| 61 * [Summary](#summary) |
| 62 * [Other resources](#other-resources) |
| 63 * [What next?](#what-next) |
| 64 |
| 65 ## Running an app with the standalone Dart VM {#run-the-first-app} |
| 66 |
| 67 To run a command-line app, you need the Dart VM (`dart`), |
| 68 which comes in the [Dart SDK download](/tools/sdk/). |
| 69 (If you downloaded Dart Editor, you already have the Dart VM.) |
| 70 |
| 71 If you installed the Dart download in a directory called `~/myDartDownload`, |
| 72 you can find `dart` |
| 73 in `~/myDartDownload/dart-sdk/bin`. |
| 74 |
| 75 <div markdown="1"> |
| 76 |
| 77  |
| 78 |
| 79 </div> |
| 80 |
| 81 By putting this directory in your PATH |
| 82 you can refer to the `dart` command and other commands, |
| 83 such as the dart analyzer, by name. |
| 84 |
| 85 Let's run a small program. |
| 86 |
| 87 <ol> |
| 88 <li markdown="1"> |
| 89 Create a file called `helloworld.dart` that contains this code: |
| 90 |
| 91 {% prettify dart %} |
| 92 void main() { |
| 93 print('Hello, World!'); |
| 94 } |
| 95 {% endprettify %} |
| 96 </li> |
| 97 |
| 98 <li markdown="1"> |
| 99 In the directory that contains the file you just created, |
| 100 run the program with the command as shown by the highlighted text. |
| 101 |
| 102 {% prettify bash %} |
| 103 % [[highlight]]dart helloworld.dart[[/highlight]] |
| 104 Hello, World! |
| 105 % |
| 106 {% endprettify %} |
| 107 |
| 108 </li> |
| 109 </ol> |
| 110 |
| 111 The Dart VM supports many options. |
| 112 Use `dart --help` to see commonly used options. |
| 113 Use `dart --verbose` to see all options. |
| 114 |
| 115 ## Review briefly the dcat example code {#dcat-code} |
| 116 |
| 117 Take a quick look at the code for a small sample called `dcat`, |
| 118 which displays the contents of any files listed on the command line. |
| 119 This program uses various classes, functions, and properties |
| 120 available to command-line apps. |
| 121 This tutorial goes into detail about this app in the following sections. |
| 122 For a brief look now, hover over the highlighted code below for explanations. |
| 123 |
| 124 <pre class="prettyprint lang-dart"> |
| 125 import 'dart:async'; |
| 126 import 'dart:convert'; |
| 127 import 'dart:io'; |
| 128 |
| 129 import 'package:args/args.dart'; |
| 130 |
| 131 const LINE_NUMBER = 'line-number'; |
| 132 var NEWLINE = '\n'; |
| 133 |
| 134 ArgResults argResults; |
| 135 |
| 136 void main(<a href="#" class="dart-popover" data-toggle="popover" title="Command-
line arguments" data-html="true" data-trigger="hover focus" data-content="Comman
d-line arguments are passed in by the system when the program starts.">List<S
tring> arguments</a>) { |
| 137 final parser = new ArgParser() |
| 138 ..addFlag(LINE_NUMBER, negatable: false, abbr: 'n'); |
| 139 |
| 140 <a href="#" class="dart-popover" data-toggle="popover" title="Arguments parser
" data-html="true" data-trigger="hover focus" data-content="The ArgParser class
provides help with parsing command-line arguments.">argResults = parser.parse(ar
guments);</a> |
| 141 List<String> paths = argResults.rest; |
| 142 |
| 143 dcat(paths, argResults[LINE_NUMBER]); |
| 144 } |
| 145 |
| 146 Future dcat(List<String> paths, bool showLineNumbers) { |
| 147 if (paths.isEmpty) { |
| 148 // No files provided as arguments. Read from stdin and print each line. |
| 149 return <a href="#" class="dart-popover" data-toggle="popover" title="Standar
d I/O streams" data-html="true" data-trigger="hover focus" data-content="This co
de reads from the standard input stream and pipes the data to the standard outpu
t stream.">stdin.pipe(stdout);</a> |
| 150 } else { |
| 151 return Future.forEach(paths, (path) { |
| 152 int lineNumber = 1; |
| 153 <a href="#" class="dart-popover" data-toggle="popover" title="Open a file
for reading" data-html="true" data-trigger="hover focus" data-content="Use the F
ile class to represent a file on the native file system.">Stream<List<int&
gt;> stream = new File(path).openRead();</a> |
| 154 return stream |
| 155 <a href="#" class="dart-popover" data-toggle="popover" title="Data con
verters" data-html="true" data-trigger="hover focus" data-content="Convert data
as it becomes available on a stream.">.transform(UTF8.decoder)</a> |
| 156 .transform(const LineSplitter()) |
| 157 <a href="#" class="dart-popover" data-toggle="popover" title="Get data
from a stream" data-html="true" data-trigger="hover focus" data-content="Listen
to a stream to get data when it becomes available.">.listen((line)</a> { |
| 158 if (showLineNumbers) { |
| 159 stdout.write('${lineNumber++} '); |
| 160 } |
| 161 stdout.writeln(line); |
| 162 }).asFuture().catchError((_) => _handleError(path)); |
| 163 }); |
| 164 } |
| 165 } |
| 166 |
| 167 _handleError(String path) { |
| 168 <a href="#" class="dart-popover" data-toggle="popover" title="Test a path" dat
a-html="true" data-trigger="hover focus" data-content="You can get information a
bout the file system on which your program is running.">FileSystemEntity.isDirec
tory(path)</a>.then((isDir) { |
| 169 if (isDir) { |
| 170 print('error: $path is a directory'); |
| 171 } else { |
| 172 print('error: $path not found'); |
| 173 } |
| 174 }); |
| 175 <a href="#" class="dart-popover" data-toggle="popover" title="Exit code" data-
html="true" data-trigger="hover focus" data-content="A well-behaved command-line
app sets an exit code to indicate whether the program was successful.">exitCode
= 2;</a> |
| 176 } |
| 177 |
| 178 </pre> |
| 179 |
| 180 ## Parsing command-line arguments {#cmd-line-args} |
| 181 |
| 182 The |
| 183 <a href="https://api.dartlang.org/args.html" target="_blank">args</a> |
| 184 package, a software bundle that contains a library of Dart code, provides |
| 185 parser support for transforming raw command-line arguments |
| 186 into a set of options, flags, and additional values. |
| 187 Import the library as follows: |
| 188 |
| 189 {% prettify dart %} |
| 190 import 'package:args/args.dart'; |
| 191 {% endprettify %} |
| 192 |
| 193 The args library contains two classes: |
| 194 |
| 195 | Library | Description | |
| 196 |---|---| |
| 197 | <a href="https://api.dartlang.org/args/ArgParser" target="_blank">ArgParser</a
> | A class that parses command-line arguments | |
| 198 | <a href="https://api.dartlang.org/args/ArgResults" target="_blank">ArgResults<
/a> | The result of parsing command-line arguments using ArgParser. | |
| 199 {: .table } |
| 200 |
| 201 Let's take a look at the `dcat` sample, |
| 202 which uses ArgParser and ArgResults to parse and store its command-line argument
s. |
| 203 |
| 204 <ol> |
| 205 <li markdown="1"> |
| 206 Copy the sample file from the github repo: |
| 207 <a href="https://github.com/dart-lang/dart-tutorials-samples/blob/master/bin/dca
t.dart">dcat.dart</a>. |
| 208 </li> |
| 209 |
| 210 <li markdown="1"> |
| 211 Run the program from the command line as shown by the highlighted text. |
| 212 |
| 213 {% prettify bash %} |
| 214 $ [[highlight]]dart dcat.dart -n quotes.txt[[/highlight]] |
| 215 1 Be yourself. Everyone else is taken. -Oscar Wilde |
| 216 2 Don't cry because it's over, smile because it happened. -Dr. Seuss |
| 217 3 You only live once, but if you do it right, once is enough. -Mae West |
| 218 ... |
| 219 {% endprettify %} |
| 220 |
| 221 The program displays the contents of the source code file and |
| 222 preceeds each line with a line number. |
| 223 </li> |
| 224 |
| 225 </ol> |
| 226 |
| 227 The following diagram shows how the `dcat` command line used above |
| 228 is parsed into the `ArgResults` object. |
| 229 |
| 230  |
| 231 |
| 232 You can access flags and options by name, |
| 233 treating the ArgResults object like a Map. |
| 234 You can access other values with properties such as `rest`. |
| 235 |
| 236 Here's the code from `dcat` that deals with command-line arguments: |
| 237 |
| 238 <pre class="prettyprint lang-dart"> |
| 239 |
| 240 ... |
| 241 <a href="#" class="dart-popover" data-toggle="popover" title="Parsed arguments"
data-html="true" data-trigger="hover focus" data-content="This object contains p
arsed options and flags.">ArgResults argResults;</a> |
| 242 |
| 243 void main(<a href="#" class="dart-popover" data-toggle="popover" title="Command-
line arguments" data-html="true" data-trigger="hover focus" data-content="The sy
stem passes command-line arguments into the program in a list of strings.">List&
lt;String> arguments</a>) { |
| 244 final parser = new ArgParser() |
| 245 <a href="#" class="dart-popover" data-toggle="popover" title="Define a val
id flag" data-html="true" data-trigger="hover focus" data-content="Add a flag de
finition to the command-line argument parser. This code defines the flag -n, whi
ch when used displays line numbers.">..addFlag(LINE_NUMBER, negatable: false, ab
br: 'n')</a>; |
| 246 |
| 247 argResults = parser.<a href="#" class="dart-popover" data-toggle="popover" tit
le="Parse the arguments" data-html="true" data-trigger="hover focus" data-conten
t="Parse the arguments that were passed into the main() function. The parser sto
ps parsing if it finds an undefined option or flag.">parse(arguments)</a>; |
| 248 List<String> paths = <a href="#" class="dart-popover" data-toggle="popov
er" title="Remaining arguments" data-html="true" data-trigger="hover focus" data
-content="To get the arguments that remain after parsing all of the valid option
s and flags, use the rest property.">argResults.rest</a>; |
| 249 |
| 250 dcat(paths, <a href="#" class="dart-popover" data-toggle="popover" title="Refe
r to options and flags by name" data-html="true" data-trigger="hover focus" data
-content="You can refer to an option or flag by name treating the ArgResults obj
ect like a Map.">argResults[LINE_NUMBER])</a>; |
| 251 } |
| 252 ... |
| 253 </pre> |
| 254 |
| 255 The |
| 256 <a href="https://api.dartlang.org/args.html" target="_blank">API docs</a> |
| 257 for the args library |
| 258 provide detailed information |
| 259 to help you use ArgsParser and ArgResults classes. |
| 260 |
| 261 ## Reading and writing with stdin, stdout, and stderr {#std-in-out-err} |
| 262 |
| 263 Like other languages, |
| 264 Dart has standard output, standard error, and standard input streams. |
| 265 The standard I/O streams are defined at the top level of the dart:io library, |
| 266 |
| 267 | Stream | Description | |
| 268 |---|---| |
| 269 | <a href="https://api.dartlang.org/dart_io.html#stdout" target="_blank">stdout<
/a> | The standard output | |
| 270 | <a href="https://api.dartlang.org/dart_io.html#stderr" target="_blank">stderr<
/a> | The standard error | |
| 271 | <a href="https://api.dartlang.org/dart_io.html#stdin" target="_blank">stdin</a
> | The standard input | |
| 272 {: .table } |
| 273 |
| 274 Import the dart:io library as follows: |
| 275 |
| 276 {% prettify dart %} |
| 277 import 'dart:io'; |
| 278 {% endprettify %} |
| 279 |
| 280 Only command-line applications, not web applications, |
| 281 can use the dart:io library. |
| 282 |
| 283 ### stdout |
| 284 |
| 285 Here's the code from the `dcat` program that writes the line number to the `stdo
ut` |
| 286 (if the -n flag is set) followed by the line from the file. |
| 287 |
| 288 {% prettify dart %} |
| 289 if (showLineNumbers) { |
| 290 [[highlight]]stdout.write('${lineNumber++} ');[[/highlight]] |
| 291 } |
| 292 |
| 293 [[highlight]]stdout.writeln(line);[[/highlight]] |
| 294 {% endprettify %} |
| 295 |
| 296 The `write()` and `writeln()` methods take an object of any type, |
| 297 convert it to a string, and print it. The `writeln()` method |
| 298 also prints a newline character. |
| 299 `dcat` uses the `write()` method to print the line number so the |
| 300 line number and the text appear on the same line. |
| 301 |
| 302 You can also use the `writeAll()` method to print a list of objects, |
| 303 or use `addStream()` to asynchronously print all of the elements from a stream. |
| 304 |
| 305 `stdout` provides more functionality than the `print()` function. |
| 306 For example, you can display the contents of a stream with `stdout`. |
| 307 However, you must use `print()` instead of `stdout` |
| 308 for programs that are converted to and run in JavaScript. |
| 309 |
| 310 ### stderr |
| 311 |
| 312 Use `stderr` to write error messages to the console. |
| 313 The standard error stream has the same methods as `stdout`, |
| 314 and you use it in the same way. |
| 315 Although both `stdout` and `stderr` print to the console, |
| 316 their output is separate |
| 317 and can be redirected or piped at the command line |
| 318 or programmatically to different destinations. |
| 319 |
| 320 This code from `dcat` prints an error message if the user |
| 321 tries to list a directory or if the file is not found. |
| 322 |
| 323 {% prettify dart %} |
| 324 if (isDir) { |
| 325 [[highlight]]stderr.writeln('error: $path is a directory');[[/highlight]] |
| 326 } else { |
| 327 [[highlight]]stderr.writeln('error: $path not found');[[/highlight]] |
| 328 } |
| 329 {% endprettify %} |
| 330 |
| 331 ### stdin |
| 332 |
| 333 The standard input stream typically |
| 334 reads data synchronously from the keyboard, |
| 335 although it can read asynchronously |
| 336 and it can get input piped in from the standard |
| 337 output of another program. |
| 338 |
| 339 Here's a small program that reads a single line from `stdin`: |
| 340 |
| 341 {% prettify dart %} |
| 342 import 'dart:io'; |
| 343 |
| 344 void main() { |
| 345 stdout.writeln('Type something'); |
| 346 String input = stdin.readLineSync(); |
| 347 stdout.writeln('You typed: $input'); |
| 348 } |
| 349 {% endprettify %} |
| 350 |
| 351 The `readLineSync()` method reads text from the standard input stream, |
| 352 blocking until the user types in text and presses return. |
| 353 This little program prints out the typed text. |
| 354 |
| 355 In the `dcat` program, |
| 356 if the user does not provide a filename on the command line, |
| 357 the program instead reads synchronously from stdin |
| 358 using the `pipe()` method. |
| 359 |
| 360 {% prettify dart %} |
| 361 return [[highlight]]stdin[[/highlight]].pipe(stdout); |
| 362 {% endprettify %} |
| 363 |
| 364 In this case, |
| 365 the user types in lines of text and the program copies them to stdout. |
| 366 The user signals the end of input by typing <ctl-d>. |
| 367 |
| 368 {% prettify bash %} |
| 369 $ [[highlight]]dart dcat.dart[[/highlight]] |
| 370 [[highlight]]The quick brown fox jumped over the lazy dog.[[/highlight]] |
| 371 The quick brown fox jumped over the lazy dog. |
| 372 ... |
| 373 {% endprettify %} |
| 374 |
| 375 ## Getting info about a file {#filesystementity} |
| 376 |
| 377 The |
| 378 <a href="https://api.dartlang.org/dart_io/FileSystemEntity.html" target="_blank"
>FileSystemEntity</a> |
| 379 class in the dart:io library provides |
| 380 properties and static methods that help you inspect and manipulate the file syst
em. |
| 381 |
| 382 For example, if you have a path, |
| 383 you can determine whether the path is a file, a directory, a link, or not found |
| 384 by using the `type()` method from the `FileSystemEntity` class. |
| 385 Because the `type()` method accesses the file system, |
| 386 it performs the check asynchronously within a Future. |
| 387 |
| 388 The following code from |
| 389 the `dcat` example uses `FileSystemEntity` to determine if the path provided |
| 390 on the command line is a directory. |
| 391 The Future returns a boolean that indicates |
| 392 if the path is a directory or not. |
| 393 |
| 394 {% prettify dart %} |
| 395 [[highlight]]FileSystemEntity.isDirectory(path)[[/highlight]].then((isDir) { |
| 396 if (isDir) { |
| 397 stderr.writeln('error: $path is a directory'); |
| 398 } else { |
| 399 stderr.writeln('error: $path not found'); |
| 400 } |
| 401 exit(2); |
| 402 }); |
| 403 {% endprettify %} |
| 404 |
| 405 Other interesting methods in the `FileSystemEntity` class |
| 406 include `isFile()`, `exists()`, `stat()`, `delete()`, |
| 407 and `rename()`, |
| 408 all of which also use a Future to return a value. |
| 409 |
| 410 FileSystemEntity is the superclass for the File, Directory, and Link classes. |
| 411 |
| 412 ## Reading a file {#reading-a-file} |
| 413 |
| 414 `dcat` opens each file listed on the command line |
| 415 with the `openRead()` method, |
| 416 which returns a stream. |
| 417 The `listen()` method registers a callback function that runs |
| 418 when data becomes available on the stream. |
| 419 The callback function writes that data to stdout. |
| 420 |
| 421 {% prettify dart %} |
| 422 return Future.forEach(paths, (path) { |
| 423 int lineNumber = 1; |
| 424 Stream<List<int>> stream = new File(path).openRead(); |
| 425 |
| 426 return stream |
| 427 ... |
| 428 [[highlight]].listen((line) { |
| 429 if (showLineNumbers) { |
| 430 stdout.write('${lineNumber++} '); |
| 431 } |
| 432 stdout.writeln(line); |
| 433 })[[/highlight]].asFuture() |
| 434 .catchError((_) => _handleError(path)); |
| 435 }); |
| 436 {% endprettify %} |
| 437 |
| 438 The following shows the rest of the |
| 439 code, which uses two decoders that transform the data before the |
| 440 `listen()` callback function runs. |
| 441 The UTF8 decoder converts the data into Dart strings. |
| 442 `LineSplitter` splits the data at newlines. |
| 443 |
| 444 {% prettify dart %} |
| 445 return Future.forEach(paths, (path) { |
| 446 int lineNumber = 1; |
| 447 Stream<List<int>> stream = new File(path).openRead(); |
| 448 |
| 449 return stream |
| 450 [[highlight]].transform(UTF8.decoder) |
| 451 .transform(const LineSplitter())[[/highlight]] |
| 452 .listen((line) { |
| 453 if (showLineNumbers) { |
| 454 stdout.write('${lineNumber++} '); |
| 455 } |
| 456 stdout.writeln(line); |
| 457 }).asFuture() |
| 458 .catchError((_) => _handleError(path)); |
| 459 }); |
| 460 {% endprettify %} |
| 461 |
| 462 The dart:convert library contains these and other data converters, including |
| 463 one for JSON. |
| 464 To use these converters you need to import the dart:convert library: |
| 465 |
| 466 {% prettify dart %} |
| 467 import 'dart:convert'; |
| 468 {% endprettify %} |
| 469 |
| 470 ## Writing a file {#writing-a-file} |
| 471 |
| 472 The easiest way to write text to a file is to |
| 473 create a |
| 474 <a href="https://api.dartlang.org/dart_io/File.html" target="_blank">File</a> |
| 475 object and use the `writeAsString()` method: |
| 476 |
| 477 {% prettify dart %} |
| 478 File quotesFile = new File('quotes.txt'); |
| 479 String stronger = 'That which does not kill us makes us stronger. -Nietzsche'; |
| 480 |
| 481 quotesFile.writeAsString(stronger, mode: FileMode.APPEND) |
| 482 .then((_) { print('Data written.'); }); |
| 483 {% endprettify %} |
| 484 |
| 485 The `writeAsString()` method writes the data asynchronously via a Future. |
| 486 It opens the file before writing and closes the file when done. |
| 487 To append data to an existing file, you can use the optional |
| 488 parameter `mode` and set its value to `FileMode.APPEND`. |
| 489 Otherwise, the mode is `FileMode.WRITE` and the previous contents of the file, |
| 490 if any, are overwritten. |
| 491 |
| 492 If you want to write more data, you can open the file for writing. |
| 493 The `openWrite()` method returns an IOSink (the same type as stdin and stderr). |
| 494 You can continue to write to the file until done, |
| 495 at which time, you must close the file. |
| 496 The `close()` method is asynchronous and returns a Future. |
| 497 |
| 498 {% prettify dart %} |
| 499 IOSink quotes = new File('quotes.txt').openWrite(mode: FileMode.APPEND); |
| 500 |
| 501 quotes.write('A woman is like a tea bag; '); |
| 502 quotes.write("you never know how strong it is until it's in hot water."); |
| 503 quotes.writeln(" -Eleanor Roosevelt"); |
| 504 quotes.close().then((_) { print('done'); } ); |
| 505 {% endprettify %} |
| 506 |
| 507 ## Getting environment information {#env-var} |
| 508 |
| 509 Use the |
| 510 <a href="https://api.dartlang.org/dart_io/Platform.html" target="_blank">Platfor
m</a> |
| 511 class |
| 512 to get information about the machine and OS that the program is running on. |
| 513 Note: Use the Platform class from the dart:io library, |
| 514 not from the dart:html library. |
| 515 |
| 516 `Platform.environment` provides a copy of the environment |
| 517 variables in a mutable map. |
| 518 |
| 519 {% prettify dart %} |
| 520 Map environmentVars = Platform.environment; |
| 521 |
| 522 print('PWD = ${environmentVars["PWD"]}'); |
| 523 print('LOGNAME = ${environmentVars["LOGNAME"]}'); |
| 524 print('PATH = ${environmentVars["PATH"]}'); |
| 525 {% endprettify %} |
| 526 |
| 527 `Platform` provides other useful properties that give |
| 528 information about the machine, OS, and currently |
| 529 running program. |
| 530 For example: |
| 531 |
| 532 * `Platform.isMacOS()` |
| 533 * `Platform.numberOfProcessors` |
| 534 * `Platform.script.path` |
| 535 |
| 536 ## Setting exit codes {#exit-codes} |
| 537 |
| 538 The dart:io library defines a top-level property, |
| 539 `exitCode`, that you can change to set the exit code for |
| 540 the current invocation of the Dart VM. |
| 541 An exit code is a number passed from |
| 542 the Dart program to the parent process |
| 543 to indicate the success, failure, or other state of the |
| 544 execution of the program. |
| 545 |
| 546 The `dcat` program sets the exit code |
| 547 in the `_handleError()` function to indicate that an error |
| 548 occcurred during execution. |
| 549 |
| 550 {% prettify dart %} |
| 551 _handleError(String path) { |
| 552 FileSystemEntity.isDirectory(path).then((isDir) { |
| 553 if (isDir) { |
| 554 stderr.writeln('error: $path is a directory'); |
| 555 } else { |
| 556 stderr.writeln('error: $path not found'); |
| 557 } |
| 558 [[highlight]]exitCode = 2;[[/highlight]] |
| 559 }); |
| 560 } |
| 561 {% endprettify %} |
| 562 |
| 563 An exit code of 2 indicates that the program encountered an error. |
| 564 |
| 565 An alternative to using `exitCode` is to use the top-level `exit()` function, |
| 566 which sets the exit code and quits the program immediately. |
| 567 For example, the `_handleError()` function could call `exit(2)` |
| 568 instead of setting `exitCode` to 2, |
| 569 but `exit()` would quit the program |
| 570 and it might not process all of the files on the command line. |
| 571 |
| 572 <aside class="alert alert-info" markdown="1"> |
| 573 Generally speaking, you are better off using the `exitCode` property, |
| 574 which sets the exit code but allows the program to continue through to its |
| 575 natural completion. |
| 576 </aside> |
| 577 |
| 578 Although you can use any number for an exit code, |
| 579 by convention, the codes in the table below have the following meanings: |
| 580 |
| 581 | Code | Meaning | |
| 582 |---|---| |
| 583 | 0 | Success | |
| 584 | 1 | Warnings | |
| 585 | 2 | Errors | |
| 586 {: .table } |
| 587 |
| 588 ## Summary {#summary} |
| 589 |
| 590 This tutorial described some basic API found in these classes from the dart:io l
ibrary: |
| 591 |
| 592 | API | Description | |
| 593 |---|---| |
| 594 | <a href="https://api.dartlang.org/dart_io/IOSink.html" target="_blank">IOSink<
/a> | Helper class for objects that consume data from streams. | |
| 595 | <a href="https://api.dartlang.org/dart_io/File.html" target="_blank">File</a>
| Represents a file on the native file system | |
| 596 | <a href="https://api.dartlang.org/dart_io/Directory.html" target="_blank">Dire
ctory</a> | Represents a directory on the native file system | |
| 597 | <a href="https://api.dartlang.org/dart_io/FileSystemEntity.html" target="_blan
k">FileSystemEntity</a> | Superclass for File and Directory | |
| 598 | <a href="https://api.dartlang.org/dart_io/Platform.html" target="_blank">Platf
orm</a> | Provides information about the machine and operating system | |
| 599 | <a href="https://api.dartlang.org/dart_io.html#stdout" target="_blank">stdout<
/a> | The standard output | |
| 600 | <a href="https://api.dartlang.org/dart_io.html#stderr" target="_blank">stderr<
/a> | The standard error | |
| 601 | <a href="https://api.dartlang.org/dart_io.html#stdin" target="_blank">stdin</a
> | The standard input | |
| 602 | <a href="https://api.dartlang.org/dart_io.html#exitCode" target="_blank">exitC
ode</a> | Sets the exit code | |
| 603 | <a href="https://api.dartlang.org/dart_io.html#exit" target="_blank">exit()</a
> | Sets the exit code and quits | |
| 604 {: .table } |
| 605 |
| 606 In addition, this tutorial covers two classes that help with command-line argume
nts: |
| 607 |
| 608 | Class | Description | |
| 609 |---|---| |
| 610 | <a href="https://api.dartlang.org/args/ArgParser" target="_blank">ArgParser</a
> | A class that transforms a list of raw arguments and into a set of options, f
lags, and remaining values. | |
| 611 | <a href="https://api.dartlang.org/args/ArgResults" target="_blank">ArgResults<
/a> | The result of parsing raw command line arguments using ArgParser. | |
| 612 {: .table } |
| 613 |
| 614 ## Other resources {#other-resources} |
| 615 |
| 616 Check out the [Command-line Apps Programmers' Guide](/docs/serverguide.html) |
| 617 to find more resources related to writing command-line apps. |
| 618 |
| 619 See the |
| 620 [Dartiverse Search walkthrough](/docs/dart-up-and-running/contents/ch05.html) |
| 621 for an example of another kind of command-line app: an HTTP server. |
| 622 |
| 623 Refer to the API docs for <a href="https://api.dartlang.org/dart_io.html" target
="_blank">dart:io</a>, |
| 624 <a href="https://api.dartlang.org/dart_async.html" target="_blank">dart:async</a
>, |
| 625 <a href="https://api.dartlang.org/dart_convert.html" target="_blank">dart:conver
t</a>, |
| 626 and the |
| 627 <a href="https://api.dartlang.org/dart_args.html" target="_blank">args</a> |
| 628 package for more classes, functions, and properties. |
| 629 |
| 630 ## What next? {#what-next} |
| 631 |
| 632 The [Get Input from a Form](/docs/tutorials/forms/) tutorial |
| 633 features a client-server. |
| 634 The code for the server, which uses CORS headers and handles |
| 635 POST requests, is explained in detail. |
| 636 |
| 637 {% endcapture %} |
| 638 |
| 639 {% include tutorial.html %} |
OLD | NEW |