Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.sejda.io; import static org.sejda.util.RequireUtils.requireNotNullArg; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.charset.StandardCharsets; import org.apache.commons.io.Charsets; import org.sejda.util.IOUtils; /** * Component providing methods to write to a {@link CountingWritableByteChannel}. This implementation is buffered and bytes are flushed to the {@link CountingWritableByteChannel} * only when the buffer is full. The buffer size is configurable using the OUTPUT_BUFFER_SIZE_PROPERTY property. * * @author Andrea Vacondio */ public class BufferedCountingChannelWriter implements Closeable { public static final String OUTPUT_BUFFER_SIZE_PROPERTY = "org.sejda.io.buffered.output.size"; private static final byte EOL = '\n'; private CountingWritableByteChannel channel; private ByteBuffer buffer = ByteBuffer.allocate(Integer.getInteger(OUTPUT_BUFFER_SIZE_PROPERTY, 4096)); private boolean onNewLine = false; public BufferedCountingChannelWriter(CountingWritableByteChannel channel) { requireNotNullArg(channel, "Cannot write to a null channell"); this.channel = channel; } @Override public void close() throws IOException { if (channel.isOpen() && buffer.position() != 0) { flush(); } IOUtils.close(channel); } public void writeEOL() throws IOException { if (!onNewLine) { write(EOL); onNewLine = true; } } /** * Writes the given string in {@link Charsets#ISO_8859_1} * * @param value * @throws IOException */ public void write(String value) throws IOException { write(value.getBytes(StandardCharsets.ISO_8859_1)); } /** * Writes the given bytes to the destination * * @param bytes * @throws IOException */ public void write(byte[] bytes) throws IOException { for (int i = 0; i < bytes.length; i++) { write(bytes[i]); } } /** * Writes the single byte to the destination * * @param myByte * @throws IOException */ public void write(byte myByte) throws IOException { onNewLine = false; buffer.put(myByte); if (!buffer.hasRemaining()) { flush(); } } /** * Writes everything that is read from the {@link InputStream} to the destination * * @param stream * @throws IOException */ public void write(InputStream stream) throws IOException { onNewLine = false; try (ReadableByteChannel readable = Channels.newChannel(stream)) { flush(); while (readable.read(buffer) != -1) { flush(); } } } /** * @return the current offset in the output */ public long offset() { return channel.count() + buffer.position(); } /** * Flush the buffer * * @throws IOException */ public void flush() throws IOException { buffer.flip(); channel.write(buffer); buffer.clear(); } }