aboutsummaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/io/CharSink.java
blob: 064adcd7c51e361b2f32ebcb619488d47fe471b2 (plain)
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
/*
 * Copyright (C) 2012 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.io;

import static com.google.common.base.Preconditions.checkNotNull;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charset;

/**
 * A destination to which characters can be written, such as a text file. Unlike a {@link Writer}, a
 * {@code CharSink} is not an open, stateful stream that can be written to and closed. Instead, it
 * is an immutable <i>supplier</i> of {@code Writer} instances.
 *
 * <p>{@code CharSink} provides two kinds of methods:
 * <ul>
 *   <li><b>Methods that return a writer:</b> These methods should return a <i>new</i>,
 *   independent instance each time they are called. The caller is responsible for ensuring that the
 *   returned writer is closed.
 *   <li><b>Convenience methods:</b> These are implementations of common operations that are
 *   typically implemented by opening a writer using one of the methods in the first category,
 *   doing something and finally closing the writer that was opened.
 * </ul>
 *
 * <p>Any {@link ByteSink} may be viewed as a {@code CharSink} with a specific {@linkplain Charset
 * character encoding} using {@link ByteSink#asCharSink(Charset)}. Characters written to the
 * resulting {@code CharSink} will written to the {@code ByteSink} as encoded bytes.
 *
 * @since 14.0
 * @author Colin Decker
 */
public abstract class CharSink {

  /**
   * Opens a new {@link Writer} for writing to this sink. This method should return a new,
   * independent writer each time it is called.
   *
   * <p>The caller is responsible for ensuring that the returned writer is closed.
   *
   * @throws IOException if an I/O error occurs in the process of opening the writer
   */
  public abstract Writer openStream() throws IOException;

  /**
   * Opens a new {@link BufferedWriter} for writing to this sink. This method should return a new,
   * independent writer each time it is called.
   *
   * <p>The caller is responsible for ensuring that the returned writer is closed.
   *
   * @throws IOException if an I/O error occurs in the process of opening the writer
   */
  public BufferedWriter openBufferedStream() throws IOException {
    Writer writer = openStream();
    return (writer instanceof BufferedWriter)
        ? (BufferedWriter) writer
        : new BufferedWriter(writer);
  }

  /**
   * Writes the given character sequence to this sink.
   *
   * @throws IOException if an I/O error in the process of writing to this sink
   */
  public void write(CharSequence charSequence) throws IOException {
    checkNotNull(charSequence);

    Closer closer = Closer.create();
    try {
      Writer out = closer.register(openStream());
      out.append(charSequence);
    } catch (Throwable e) {
      throw closer.rethrow(e);
    } finally {
      closer.close();
    }
  }

  /**
   * Writes the given lines of text to this sink with each line (including the last) terminated with
   * the operating system's default line separator. This method is equivalent to
   * {@code writeLines(lines, System.getProperty("line.separator"))}.
   *
   * @throws IOException if an I/O error occurs in the process of writing to this sink
   */
  public void writeLines(Iterable<? extends CharSequence> lines) throws IOException {
    writeLines(lines, System.getProperty("line.separator"));
  }

  /**
   * Writes the given lines of text to this sink with each line (including the last) terminated with
   * the given line separator.
   *
   * @throws IOException if an I/O error occurs in the process of writing to this sink
   */
  public void writeLines(Iterable<? extends CharSequence> lines, String lineSeparator)
      throws IOException {
    checkNotNull(lines);
    checkNotNull(lineSeparator);

    Closer closer = Closer.create();
    try {
      BufferedWriter out = closer.register(openBufferedStream());
      for (CharSequence line : lines) {
        out.append(line).append(lineSeparator);
      }
    } catch (Throwable e) {
      throw closer.rethrow(e);
    } finally {
      closer.close();
    }
  }

  /**
   * Writes all the text from the given {@link Readable} (such as a {@link Reader}) to this sink.
   * Does not close {@code readable} if it is {@code Closeable}.
   *
   * @throws IOException if an I/O error occurs in the process of reading from {@code readable} or
   *     writing to this sink
   */
  public long writeFrom(Readable readable) throws IOException {
    checkNotNull(readable);

    Closer closer = Closer.create();
    try {
      Writer out = closer.register(openStream());
      return CharStreams.copy(readable, out);
    } catch (Throwable e) {
      throw closer.rethrow(e);
    } finally {
      closer.close();
    }
  }
}