• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LearnLib / automatalib / 10220057657

02 Aug 2024 06:06PM UTC coverage: 90.366% (+0.3%) from 90.072%
10220057657

push

github

mtf90
overhaul serizalition code

* unify access to Input(De)Serializers behind facades to leverage the default methods for various input/output channels
* drop implicit buffering/decompressing as this should be decided where the stream are constructed (user-land)
* remove/cleanup the (now) unused code

300 of 349 new or added lines in 33 files covered. (85.96%)

9 existing lines in 3 files now uncovered.

15927 of 17625 relevant lines covered (90.37%)

1.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.24
/commons/util/src/main/java/net/automatalib/common/util/IOUtil.java
1
/* Copyright (C) 2013-2024 TU Dortmund University
2
 * This file is part of AutomataLib, http://www.automatalib.net/.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package net.automatalib.common.util;
17

18
import java.io.BufferedInputStream;
19
import java.io.BufferedOutputStream;
20
import java.io.ByteArrayInputStream;
21
import java.io.ByteArrayOutputStream;
22
import java.io.File;
23
import java.io.IOException;
24
import java.io.InputStream;
25
import java.io.InputStreamReader;
26
import java.io.OutputStream;
27
import java.io.OutputStreamWriter;
28
import java.io.Reader;
29
import java.io.StringWriter;
30
import java.io.Writer;
31
import java.nio.charset.StandardCharsets;
32
import java.nio.file.Files;
33
import java.util.zip.GZIPInputStream;
34

35
import net.automatalib.common.util.io.NonClosingInputStream;
36
import net.automatalib.common.util.io.NonClosingOutputStream;
37

38
/**
39
 * Utility methods for operating with {@code java.io.*} classes.
40
 */
41
public final class IOUtil {
42

43
    public static final int DEFAULT_BUFFER_SIZE = 4096;
44

45
    private IOUtil() {
46
        // prevent instantiation
47
    }
48

49
    /**
50
     * Ensures that the returned stream is an uncompressed version of the supplied input stream.
51
     * <p>
52
     * This method first tries to read the first two bytes from the stream, then resets the stream. If the first two
53
     * bytes equal the GZip magic number (see {@link GZIPInputStream#GZIP_MAGIC}), the supplied stream is wrapped in a
54
     * {@link GZIPInputStream}. Otherwise, the stream is returned as-is.
55
     * <p>
56
     * Note: this requires the input stream to {@link InputStream#markSupported() support marking}.
57
     *
58
     * @param is
59
     *         the input stream
60
     *
61
     * @return an uncompressed version of {@code is}
62
     *
63
     * @throws IOException
64
     *         if reading the magic number fails
65
     * @throws IllegalArgumentException
66
     *         if the stream does not support {@link InputStream#markSupported() marking}
67
     */
68
    public static InputStream asUncompressedInputStream(InputStream is) throws IOException {
69
        if (!is.markSupported()) {
2✔
70
            throw new IllegalArgumentException("input stream must support marking");
×
71
        }
72

73
        is.mark(2);
2✔
74
        byte[] buf = new byte[2];
2✔
75
        int bytesRead;
76
        try {
77
            bytesRead = is.read(buf);
2✔
78
        } finally {
79
            is.reset();
2✔
80
        }
81
        if (bytesRead == 2) {
2✔
82
            final int byteMask = 0xff;
2✔
83
            final int byteWidth = 8;
2✔
84
            int magic = (buf[1] & byteMask) << byteWidth | (buf[0] & byteMask);
2✔
85
            if (magic == GZIPInputStream.GZIP_MAGIC) {
2✔
86
                return new GZIPInputStream(is);
2✔
87
            }
88
        }
89
        return is;
2✔
90
    }
91

92
    /**
93
     * Ensures that the returned stream is a buffered version of the supplied input stream. The result must not
94
     * necessarily be an instance of {@link BufferedInputStream}, it can also be, e.g., a {@link ByteArrayInputStream},
95
     * depending on the type of the supplied input stream.
96
     *
97
     * @param is
98
     *         the input stream
99
     *
100
     * @return a buffered version of {@code is}
101
     */
102
    public static InputStream asBufferedInputStream(InputStream is) {
103
        if (isBufferedInputStream(is)) {
1✔
104
            return is;
1✔
105
        }
106
        return new BufferedInputStream(is);
1✔
107
    }
108

109
    /**
110
     * Returns an input stream that reads the contents of the given file. Additionally, buffers the input stream to
111
     * improve performance.
112
     *
113
     * @param file
114
     *         the file to read
115
     *
116
     * @return a buffered input stream for the file contents
117
     *
118
     * @throws IOException
119
     *         if accessing the file results in an I/O error
120
     */
121
    public static InputStream asBufferedInputStream(File file) throws IOException {
122
        return asBufferedInputStream(Files.newInputStream(file.toPath()));
1✔
123
    }
124

125
    /**
126
     * Ensures that the returned stream is a buffered version of the supplied output stream. The result must not
127
     * necessarily be an instance of {@link BufferedOutputStream}, it can also be, e.g., a
128
     * {@link ByteArrayOutputStream}, depending on the type of the supplied output stream.
129
     *
130
     * @param os
131
     *         the output stream
132
     *
133
     * @return a buffered version of {@code os}
134
     */
135
    public static OutputStream asBufferedOutputStream(OutputStream os) {
136
        if (isBufferedOutputStream(os)) {
2✔
137
            return os;
2✔
138
        }
139
        return new BufferedOutputStream(os);
2✔
140
    }
141

142
    /**
143
     * Returns an output stream that writes the contents to the given file. Additionally, buffers the input stream to
144
     * improve performance.
145
     *
146
     * @param file
147
     *         the file to write to
148
     *
149
     * @return a buffered output stream for the file contents
150
     *
151
     * @throws IOException
152
     *         if accessing the file results in an I/O error
153
     */
154
    public static OutputStream asBufferedOutputStream(File file) throws IOException {
155
        return asBufferedOutputStream(Files.newOutputStream(file.toPath()));
1✔
156
    }
157

158
    /**
159
     * Returns a reader that parses the contents of the given file with {@link StandardCharsets#UTF_8} encoding.
160
     * Additionally, buffers the input stream to improve performance.
161
     *
162
     * @param file
163
     *         the file to read
164
     *
165
     * @return a buffered, UTF-8-decoding reader for the file contents
166
     *
167
     * @throws IOException
168
     *         if accessing the file results in an I/O error
169
     */
170
    public static Reader asBufferedUTF8Reader(File file) throws IOException {
171
        return Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8);
1✔
172
    }
173

174
    /**
175
     * Returns a reader that parses the contents of the given input stream with {@link StandardCharsets#UTF_8} encoding.
176
     * If the given input stream is not already a buffering input stream, additionally buffers the input stream to
177
     * improve performance.
178
     * <p>
179
     * Implementation note: the input stream (byte-wise representation) will be buffered, not the reader (character-wise
180
     * representation).
181
     *
182
     * @param is
183
     *         the input stream to read
184
     *
185
     * @return a buffered, UTF-8-decoding reader for the input stream.
186
     */
187
    public static Reader asBufferedUTF8Reader(InputStream is) {
188
        return asUTF8Reader(asBufferedInputStream(is));
1✔
189
    }
190

191
    /**
192
     * Returns a reader that parses the contents of the given input stream with {@link StandardCharsets#UTF_8} encoding
193
     * and does not propagate calls to {@link InputStream#close()}.
194
     *
195
     * @param is
196
     *         the input stream to read
197
     *
198
     * @return a non-closing, UTF-8-decoding reader for the input stream.
199
     */
200
    public static Reader asNonClosingUTF8Reader(InputStream is) {
201
        return asUTF8Reader(new NonClosingInputStream(is));
1✔
202
    }
203

204
    /**
205
     * Returns a reader that parses the contents of the given input stream with {@link StandardCharsets#UTF_8} encoding.
206
     *
207
     * @param is
208
     *         the input stream to read
209
     *
210
     * @return a UTF-8-decoding reader for the input stream
211
     */
212
    public static Reader asUTF8Reader(InputStream is) {
213
        return new InputStreamReader(is, StandardCharsets.UTF_8);
2✔
214
    }
215

216
    /**
217
     * Returns a writer that writes contents to the given file with {@link StandardCharsets#UTF_8} encoding.
218
     * Additionally, buffers the input stream to improve performance.
219
     *
220
     * @param file
221
     *         the file to write to
222
     *
223
     * @return a buffered, UTF-8-encoding writer for the file contents
224
     *
225
     * @throws IOException
226
     *         if writing to the file results in I/O errors
227
     */
228
    public static Writer asBufferedUTF8Writer(File file) throws IOException {
229
        return Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8);
1✔
230
    }
231

232
    /**
233
     * Returns a writer that writes contents to the given output stream with {@link StandardCharsets#UTF_8} encoding. If
234
     * the given output stream is not already a buffering output stream, additionally buffers the output stream to
235
     * improve performance.
236
     * <p>
237
     * Implementation note: the output stream (byte-wise representation) will be buffered, not the writer (character-
238
     * wise representation).
239
     *
240
     * @param os
241
     *         the output stream to write to
242
     *
243
     * @return a buffered, UTF-8 encoding writer for the output stream
244
     */
245
    public static Writer asBufferedUTF8Writer(OutputStream os) {
246
        return asUTF8Writer(asBufferedOutputStream(os));
2✔
247
    }
248

249
    /**
250
     * Returns a writer that writes contents to the given output stream with {@link StandardCharsets#UTF_8} encoding and
251
     * propagates calls to {@link OutputStream#close()} to {@link OutputStream#flush()}.
252
     *
253
     * @param os
254
     *         the output stream to write to
255
     *
256
     * @return a non-closing, UTF-8 encoding writer for the output stream
257
     */
258
    public static Writer asNonClosingUTF8Writer(OutputStream os) {
259
        return asUTF8Writer(new NonClosingOutputStream(os));
1✔
260
    }
261

262
    /**
263
     * Returns a writer that writes contents to the given output stream with {@link StandardCharsets#UTF_8} encoding.
264
     *
265
     * @param os
266
     *         the output stream to write to
267
     *
268
     * @return a UTF-8-encoding writer for the output stream.
269
     */
270
    public static Writer asUTF8Writer(OutputStream os) {
271
        return new OutputStreamWriter(os, StandardCharsets.UTF_8);
2✔
272
    }
273

274
    /**
275
     * Returns a buffered input stream that de-compresses the contents of {@code is} (in case the given input stream
276
     * contains gzip'ed content).
277
     *
278
     * @param is
279
     *         the input stream to read
280
     *
281
     * @return a (potentially) de-compressed, buffered version of {@code is}
282
     *
283
     * @throws IOException
284
     *         if reading the stream (for detecting whether it contains compressed contents) fails
285
     * @see #asBufferedInputStream(InputStream)
286
     * @see #asUncompressedInputStream(InputStream)
287
     */
288
    public static InputStream asUncompressedBufferedInputStream(InputStream is) throws IOException {
UNCOV
289
        if (isBufferedInputStream(is)) {
×
NEW
290
            return asUncompressedInputStream(is);
×
291
        }
292

NEW
293
        return asUncompressedInputStream(asBufferedInputStream(is));
×
294
    }
295

296
    private static boolean isBufferedInputStream(InputStream is) {
297
        return is instanceof BufferedInputStream || is instanceof ByteArrayInputStream;
1✔
298
    }
299

300
    private static boolean isBufferedOutputStream(OutputStream os) {
301
        return os instanceof BufferedOutputStream || os instanceof ByteArrayOutputStream;
2✔
302
    }
303

304
    /**
305
     * Copies the contents of the given reader into the given writer.
306
     *
307
     * @param in
308
     *         the reader to read data from
309
     * @param out
310
     *         the writer to write data to
311
     *
312
     * @throws IOException
313
     *         if reading from or writing to the respective reader / writer throws this exception
314
     */
315
    public static void copy(Reader in, Writer out) throws IOException {
316
        final char[] buf = new char[DEFAULT_BUFFER_SIZE];
1✔
317
        int read;
318
        while ((read = in.read(buf)) >= 0) {
1✔
319
            out.write(buf, 0, read);
1✔
320
        }
321
    }
1✔
322

323
    /**
324
     * Reads the data from the given reader and returns its contents as a string.
325
     *
326
     * @param r
327
     *         the reader to read data from
328
     *
329
     * @return the contents of the reader as a string
330
     *
331
     * @throws IOException
332
     *         if reading from the reader throws this exception
333
     */
334
    public static String toString(Reader r) throws IOException {
335
        final StringWriter w = new StringWriter();
1✔
336
        copy(r, w);
1✔
337
        return w.toString();
1✔
338
    }
339
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc