1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.io.input;
19
20 import java.io.BufferedReader;
21 import java.io.IOException;
22 import java.io.Reader;
23 import java.io.UncheckedIOException;
24 import java.nio.CharBuffer;
25
26 import org.apache.commons.io.build.AbstractStreamBuilder;
27 import org.apache.commons.io.function.Uncheck;
28
29 /**
30 * A {@link BufferedReader} that throws {@link UncheckedIOException} instead of {@link IOException}.
31 * <p>
32 * To build an instance, use {@link Builder}.
33 * </p>
34 *
35 * @see Builder
36 * @see BufferedReader
37 * @see IOException
38 * @see UncheckedIOException
39 * @since 2.12.0
40 */
41 public final class UncheckedBufferedReader extends BufferedReader {
42
43 // @formatter:off
44 /**
45 * Builds a new {@link UncheckedBufferedReader}.
46 *
47 * <p>
48 * Using File IO:
49 * </p>
50 * <pre>{@code
51 * UncheckedBufferedReader s = UncheckedBufferedReader.builder()
52 * .setFile(file)
53 * .setBufferSize(8192)
54 * .setCharset(Charset.defaultCharset())
55 * .get();}
56 * </pre>
57 * <p>
58 * Using NIO Path:
59 * </p>
60 * <pre>{@code
61 * UncheckedBufferedReader s = UncheckedBufferedReader.builder()
62 * .setPath(path)
63 * .setBufferSize(8192)
64 * .setCharset(Charset.defaultCharset())
65 * .get();}
66 * </pre>
67 *
68 * @see #get()
69 */
70 // @formatter:on
71 public static class Builder extends AbstractStreamBuilder<UncheckedBufferedReader, Builder> {
72
73 /**
74 * Constructs a new builder of {@link UncheckedBufferedReader}.
75 */
76 public Builder() {
77 // empty
78 }
79
80 /**
81 * Builds a new {@link UncheckedBufferedReader}.
82 *
83 * <p>
84 * You must set an aspect that supports {@link #getReader()} on this builder, otherwise, this method throws an exception.
85 * </p>
86 * <p>
87 * This builder uses the following aspects:
88 * </p>
89 * <ul>
90 * <li>{@link #getReader()} gets the target aspect.</li>
91 * <li>{@link #getBufferSize()}</li>
92 * </ul>
93 *
94 * @return a new instance.
95 * @throws UnsupportedOperationException if the origin cannot provide a {@link Reader}.
96 * @throws IllegalStateException if the {@code origin} is {@code null}.
97 * @see #getReader()
98 * @see #getBufferSize()
99 * @see #getUnchecked()
100 */
101 @SuppressWarnings("resource")
102 @Override
103 public UncheckedBufferedReader get() {
104 // This an unchecked class, so this method is as well.
105 return Uncheck.get(() -> new UncheckedBufferedReader(getReader(), getBufferSize()));
106 }
107
108 }
109
110 /**
111 * Constructs a new {@link Builder}.
112 *
113 * @return a new {@link Builder}.
114 */
115 public static Builder builder() {
116 return new Builder();
117 }
118
119 /**
120 * Constructs a buffering character-input stream that uses an input buffer of the specified size.
121 *
122 * @param reader A Reader
123 * @param bufferSize Input-buffer size
124 * @throws IllegalArgumentException If {@code bufferSize <= 0}
125 */
126 private UncheckedBufferedReader(final Reader reader, final int bufferSize) {
127 super(reader, bufferSize);
128 }
129
130 /**
131 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
132 */
133 @Override
134 public void close() throws UncheckedIOException {
135 Uncheck.run(super::close);
136 }
137
138 /**
139 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
140 */
141 @Override
142 public void mark(final int readAheadLimit) throws UncheckedIOException {
143 Uncheck.accept(super::mark, readAheadLimit);
144 }
145
146 /**
147 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
148 */
149 @Override
150 public int read() throws UncheckedIOException {
151 return Uncheck.getAsInt(super::read);
152 }
153
154 /**
155 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
156 */
157 @Override
158 public int read(final char[] cbuf) throws UncheckedIOException {
159 return Uncheck.apply(super::read, cbuf);
160 }
161
162 /**
163 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
164 */
165 @Override
166 public int read(final char[] cbuf, final int off, final int len) throws UncheckedIOException {
167 return Uncheck.apply(super::read, cbuf, off, len);
168 }
169
170 /**
171 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
172 */
173 @Override
174 public int read(final CharBuffer target) throws UncheckedIOException {
175 return Uncheck.apply(super::read, target);
176 }
177
178 /**
179 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
180 */
181 @Override
182 public String readLine() throws UncheckedIOException {
183 return Uncheck.get(super::readLine);
184 }
185
186 /**
187 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
188 */
189 @Override
190 public boolean ready() throws UncheckedIOException {
191 return Uncheck.getAsBoolean(super::ready);
192 }
193
194 /**
195 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
196 */
197 @Override
198 public void reset() throws UncheckedIOException {
199 Uncheck.run(super::reset);
200 }
201
202 /**
203 * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
204 */
205 @Override
206 public long skip(final long n) throws UncheckedIOException {
207 return Uncheck.apply(super::skip, n);
208 }
209
210 }