A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

今天来学习PrintWriter。

PrintWriter,字符类型的打印输出流,用于控制文本输出流打印对象的格式化表示形式。此类实现在PrintStream中的所有print方法。它不包含用于写入原始字节的方法。

此类中的方法不会抛出I/O异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用checkError()是否出现错误。

ps:如果不想看源码,文章末尾有对源码的总结。

源码

下面看下PrintWriter的源码。

public class PrintWriter extends Writer {    /**     * PrintWriter的底层字符输出流     */    protected Writer out;    //是否自动刷新。    //如果为true,每次执行print(), println(), write()函数,都会调用flush()函数。    private final boolean autoFlush;    //是否有异常    //当PrintWriter有异常产生时,会被本身捕获,并设置trouble为true    private boolean trouble = false;    //用于格式化字符串的对象    private Formatter formatter;    //字节打印流    //用于checkError方法    private PrintStream psOut = null;    /**     * 行分隔符     * 在PrintWriter被创建时line.separator属性的值。     */    private final String lineSeparator;    /**     * 返回csn(字符集名字)对应的Chaset     * csn为null或是不支持的字符集,抛出异常     */    private static Charset toCharset(String csn)        throws UnsupportedEncodingException    {        Objects.requireNonNull(csn, "charsetName");        try {            return Charset.forName(csn);        } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {            // UnsupportedEncodingException should be thrown            throw new UnsupportedEncodingException(csn);        }    }    /**     * 创建新的PrintWriter。     * 指定底层输出流,默认不会自动flush,采用默认字符集     */    public PrintWriter (Writer out) {        this(out, false);    }    /**     * 创建新的PrintWriter。     * 指定底层输出流,指定是否自动flush,采用默认字符集     */    public PrintWriter(Writer out,                       boolean autoFlush) {        super(out);        this.out = out;        this.autoFlush = autoFlush;        //line.separator属性的值        lineSeparator = java.security.AccessController.doPrivileged(            new sun.security.action.GetPropertyAction("line.separator"));    }    /**     * 创建新的PrintWriter。     * 指定底层输出流,不自动flush,采用默认字符集     */    public PrintWriter(OutputStream out) {        this(out, false);    }    /**     * 创建新的PrintWriter。     * 指定底层输出流,指定是否自动flush,采用默认字符集     */    public PrintWriter(OutputStream out, boolean autoFlush) {        this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);        // save print stream for error propagation        if (out instanceof java.io.PrintStream) {            psOut = (PrintStream) out;        }    }    /**     * 创建新的PrintWriter。     * 指定文件名,默认不自动flush,采用默认字符集     */    public PrintWriter(String fileName) throws FileNotFoundException {        this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),             false);    }    /**     * 私有构造方法。创建新的PrintWriter。     * 指定文件名,默认不自动flush,采用指定字符集     */    private PrintWriter(Charset charset, File file)        throws FileNotFoundException    {        this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)),             false);    }    /**     * 创建新的PrintWriter。     * 指定文件名,默认不自动flush,采用指定字符集     */    public PrintWriter(String fileName, String csn)        throws FileNotFoundException, UnsupportedEncodingException    {        this(toCharset(csn), new File(fileName));    }    /**     * 创建新的PrintWriter。     * 指定文件名,默认不自动flush,采用默认字符集     */    public PrintWriter(File file) throws FileNotFoundException {        this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),             false);    }    /**     * 创建新的PrintWriter。     * 指定文件名,默认不自动flush,采用指定字符集     */    public PrintWriter(File file, String csn)        throws FileNotFoundException, UnsupportedEncodingException    {        this(toCharset(csn), file);    }    /** 确认输出流是否开启。如果底层输出流不为null,则认为输出流是开启的 */    private void ensureOpen() throws IOException {        if (out == null)            throw new IOException("Stream closed");    }    /**     * 刷新流     * @see #checkError()     */    public void flush() {        try {            synchronized (lock) {                ensureOpen();                out.flush();             }        }        catch (IOException x) {            //当PrintWriter有异常产生时,会被本身捕获,并设置trouble为true            trouble = true;        }    }    /**     * 关闭该流并释放与之关联的所有系统资源。     * 将底层输出流置为null,就把输出流关闭了     *     * @see #checkError()     */    public void close() {        try {            synchronized (lock) {                if (out == null)                    return;                out.close();                out = null;            }        }        catch (IOException x) {            trouble = true;        }    }    /**     * 如果流没有关闭,则刷新流且检查其错误状态。     */    public boolean checkError() {        //如果流没有关闭,则刷新流        if (out != null) {            flush();        }        //检查错误状态        if (out instanceof java.io.PrintWriter) {            PrintWriter pw = (PrintWriter) out;            return pw.checkError();        } else if (psOut != null) {            return psOut.checkError();        }        //如果抛出了异常,返回true        return trouble;    }    /**     * 指示已发生错误。     * 在调用clearError()之前,此方法将导致checkError()的后续调用返回 true。     */    protected void setError() {        trouble = true;    }    /**     * 清除此流的错误状态。     */    protected void clearError() {        trouble = false;    }    /**     * 写入单个字符。     */    public void write(int c) {        try {            synchronized (lock) {                ensureOpen();                //调用底层输出流写入单个字符                out.write(c);            }        }        catch (InterruptedIOException x) {            Thread.currentThread().interrupt();        }        catch (IOException x) {            trouble = true;        }    }    /**     * 写入字符数组的某一部分。     */    public void write(char buf[], int off, int len) {        try {            synchronized (lock) {                ensureOpen();                //调用底层输出流写入字符数组的某一部分                out.write(buf, off, len);            }        }        catch (InterruptedIOException x) {            Thread.currentThread().interrupt();        }        catch (IOException x) {            trouble = true;        }    }    /**     * 写入字符数组。     * 此方法不能从Writer类继承,因为它必须取消I/O异常。     */    public void write(char buf[]) {        write(buf, 0, buf.length);    }    /**     * 写入字符串的某一部分。     */    public void write(String s, int off, int len) {        try {            synchronized (lock) {                ensureOpen();                out.write(s, off, len);            }        }        catch (InterruptedIOException x) {            Thread.currentThread().interrupt();        }        catch (IOException x) {            trouble = true;        }    }    /**     * 写入字符串。     * 此方法不能从Writer类继承,因为它必须取消I/O异常。     */    public void write(String s) {        write(s, 0, s.length());    }    //写入换行符    private void newLine() {        try {            synchronized (lock) {                ensureOpen();                out.write(lineSeparator);                if (autoFlush)                    out.flush();            }        }        catch (InterruptedIOException x) {            Thread.currentThread().interrupt();        }        catch (IOException x) {            trouble = true;        }    }    /* Methods that do not terminate lines */    /**     * 打印boolean值。     * 按照平台的默认字符编码将字符串转换为字节,然后写入输出流。     */    public void print(boolean b) {        write(b ? "true" : "false");    }    /**     * 打印字符。     */    public void print(char c) {        write(c);    }    /**     * 打印整数。     * 按照平台的默认字符编码将字符串转换为字节,然后写入输出流。     */    public void print(int i) {        write(String.valueOf(i));    }    /**     * 打印long。     * 按照平台的默认字符编码将字符串转换为字节,然后写入输出流。     */    public void print(long l) {        write(String.valueOf(l));    }    /**     * 打印一个浮点数。     * 按照平台的默认字符编码将字符串转换为字节,然后写入输出流。     */    public void print(float f) {        write(String.valueOf(f));    }    /**     * 打印double精度浮点数。     * 按照平台的默认字符编码将字符串转换为字节,然后写入输出流。     */    public void print(double d) {        write(String.valueOf(d));    }    /**     * 打印字符数组。     * 按照平台的默认字符编码将字符转换为字节,然后写入输出流。     */    public void print(char s[]) {        write(s);    }    /**     * 打印字符串。     * 如果参数为null,则打印字符串"null"     * 否则,按照平台的默认字符编码将字符串的字符转换为字节,然后写入输出流。     */    public void print(String s) {        if (s == null) {            s = "null";        }        write(s);    }    /**     * 打印对象。     * 按照平台的默认字符串编码将String.valueOf(Object)方法生成的字符串转换为字节,     * 并完全以 write(int) 方法的方式写入这些字节。     */    public void print(Object obj) {        write(String.valueOf(obj));    }    /* Methods that do terminate lines */    /**     * 通过写入行分隔符字符串终止当前行。     * 行分隔符字符串由系统属性line.separator定义,不一定是单个换行符('\n')。     */    public void println() {        newLine();    }    /**     * 打印boolean值,然后终止该行。     */    public void println(boolean x) {        synchronized (lock) {            print(x);            println();        }    }    /**     * 打印字符,然后终止该行。     */    public void println(char x) {        synchronized (lock) {            print(x);            println();        }    }    /**     * 打印整数,然后终止该行。     */    public void println(int x) {        synchronized (lock) {            print(x);            println();        }    }    /**     * 打印long整数,然后终止该行。     */    public void println(long x) {        synchronized (lock) {            print(x);            println();        }    }    /**     * 打印浮点数,然后终止该行。     */    public void println(float x) {        synchronized (lock) {            print(x);            println();        }    }    /**     * 打印双精度浮点数,然后终止该行。     */    public void println(double x) {        synchronized (lock) {            print(x);            println();        }    }    /**     * 打印字符数组,然后终止该行。     */    public void println(char x[]) {        synchronized (lock) {            print(x);            println();        }    }    /**     * 打印String,然后终止该行。     */    public void println(String x) {        synchronized (lock) {            print(x);            println();        }    }    /**     * 打印Object,然后终止该行。     */    public void println(Object x) {        String s = String.valueOf(x);        synchronized (lock) {            print(s);            println();        }    }    /**     * 使用指定格式字符串和参数将一个格式化字符串写入此writer中。     * 如果启用自动刷新,则调用此方法将刷新输出缓冲区。     *     * @param  format 在格式字符串的语法中描述的格式字符串。     * 格式字符串的语法可以参考http://tool.oschina.net/uploads/ ... rmatter.html#syntax     *     * @param  args     *         格式字符串中的格式说明符引用的参数。如果参数多于格式说明符,则忽略额外的参数。参数的数量是可变的,并且可以为零。     *     * @since  1.5     */    public PrintWriter printf(String format, Object ... args) {        return format(format, args);    }    /**     * 使用指定格式字符串和参数将一个格式化字符串写入此writer中。     * 如果启用自动刷新,则调用此方法将刷新输出缓冲区。     *     * @param  l     *         格式化过程中应用的locale。如果l为null,则不应用本地化。     *     * @param  format     *          在格式字符串的语法中描述的格式字符串。     *     * @param  args     *         格式字符串中的格式说明符引用的参数。     *     * @since  1.5     */    public PrintWriter printf(Locale l, String format, Object ... args) {        return format(l, format, args);    }    /**     * 参考public PrintWriter printf(String format, Object... args)          */    public PrintWriter format(String format, Object ... args) {        try {            synchronized (lock) {                ensureOpen();                if ((formatter == null)                    || (formatter.locale() != Locale.getDefault()))                    formatter = new Formatter(this);                formatter.format(Locale.getDefault(), format, args);                if (autoFlush)                    out.flush();            }        } catch (InterruptedIOException x) {            Thread.currentThread().interrupt();        } catch (IOException x) {            trouble = true;        }        return this;    }    /**     * 参考printf(Locale l, String format, Object... args)     */    public PrintWriter format(Locale l, String format, Object ... args) {        try {            synchronized (lock) {                ensureOpen();                if ((formatter == null) || (formatter.locale() != l))                    formatter = new Formatter(this, l);                formatter.format(l, format, args);                if (autoFlush)                    out.flush();            }        } catch (InterruptedIOException x) {            Thread.currentThread().interrupt();        } catch (IOException x) {            trouble = true;        }        return this;    }    /**     * 将指定的字符序列添加到此writer。     * 可能不添加整个序列,也可能添加,具体取决于字符序列csq的toString指定。     *     * @since  1.5     */    public PrintWriter append(CharSequence csq) {        if (csq == null)            write("null");        else            write(csq.toString());        return this;    }    /**     * 将指定字符序列的子序列添加到此writer。     *     * @since  1.5     */    public PrintWriter append(CharSequence csq, int start, int end) {        CharSequence cs = (csq == null ? "null" : csq);        write(cs.subSequence(start, end).toString());        return this;    }    /**     * 将指定字符添加到此 writer。     *     * @since 1.5     */    public PrintWriter append(char c) {        write(c);        return this;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534
  • 535
  • 536
  • 537
  • 538
  • 539
  • 540
  • 541
  • 542
  • 543
  • 544
  • 545
  • 546
  • 547
  • 548
  • 549
  • 550
  • 551
  • 552
  • 553
  • 554
  • 555
  • 556
  • 557
  • 558
  • 559
  • 560
  • 561
  • 562
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • 573
  • 574
  • 575
  • 576
  • 577
  • 578
  • 579
  • 580
  • 581
  • 582
  • 583
  • 584
  • 585
  • 586
  • 587
  • 588
  • 589
  • 590
  • 591
  • 592
总结
  • 从构造方法中可以看到,BufferedWriter包装了底层输出流,为其提供了缓冲功能。
  • 此类中的方法不会抛出I/O异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用checkError()是否出现错误。
  • print方法可以打印boolean、char 、char[]、double 、float、int、 long、Object、String这些类型。都是按照平台的默认字符串编码将String.valueOf() 方法生成的字符串转换为字节,并完全以write(int)方法的方式向输出流中写入这些字节。
  • println(type param)方法可以打印boolean、char 、char[]、double 、float、int、 long、Object、String这些类型。都是先调用print方法打印,再调用println()方法换行。
  • printf方法和format方法的效果是相同的。因为printf方法是依赖于调用format方法实现的。
  • append方法其实是依赖于out.write方法实现的。

关于PrintWriter就讲到这里,想了解更多内容请参考

版权声明


1 个回复

倒序浏览

很不错,受教了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马