001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.io.output; 019 020import java.io.IOException; 021import java.io.Writer; 022import java.util.Objects; 023 024import org.apache.commons.io.IOUtils; 025 026/** 027 * Writer implementation that writes the data to an {@link Appendable} Object. 028 * <p> 029 * For example, can be used with a {@link StringBuilder} or {@link StringBuffer}. 030 * </p> 031 * 032 * @since 2.7 033 * @see Appendable 034 * @param <T> The type of the {@link Appendable} wrapped by this AppendableWriter. 035 */ 036public class AppendableWriter<T extends Appendable> extends Writer { 037 038 private final T appendable; 039 040 /** 041 * Constructs a new instance with the specified appendable. 042 * 043 * @param appendable the appendable to write to. 044 */ 045 public AppendableWriter(final T appendable) { 046 this.appendable = appendable; 047 } 048 049 /** 050 * Appends the specified character to the underlying appendable. 051 * 052 * @param c the character to append. 053 * @return this writer. 054 * @throws IOException If an I/O error occurs. 055 */ 056 @Override 057 public Writer append(final char c) throws IOException { 058 appendable.append(c); 059 return this; 060 } 061 062 /** 063 * Appends the specified character sequence to the underlying appendable. 064 * 065 * @param csq the character sequence to append. 066 * @return this writer. 067 * @throws IOException If an I/O error occurs. 068 */ 069 @Override 070 public Writer append(final CharSequence csq) throws IOException { 071 appendable.append(csq); 072 return this; 073 } 074 075 /** 076 * Appends a subsequence of the specified character sequence to the underlying appendable. 077 * 078 * @param csq the character sequence from which a subsequence will be appended 079 * @param start the index of the first character in the subsequence 080 * @param end the index of the character following the last character in the subsequence 081 * @return this writer 082 * @throws IndexOutOfBoundsException If {@code start} or {@code end} are negative, {@code start} is greater than 083 * {@code end}, or {@code end} is greater than {@code csq.length()}. 084 * @throws IOException If an I/O error occurs. 085 */ 086 @Override 087 public Writer append(final CharSequence csq, final int start, final int end) throws IOException { 088 appendable.append(csq, start, end); 089 return this; 090 } 091 092 /** 093 * Closes the stream. This implementation does nothing. 094 * 095 * @throws IOException Thrown by a subclass. 096 */ 097 @Override 098 public void close() throws IOException { 099 // noop 100 } 101 102 /** 103 * Flushes the stream. This implementation does nothing. 104 * 105 * @throws IOException Thrown by a subclass. 106 */ 107 @Override 108 public void flush() throws IOException { 109 // noop 110 } 111 112 /** 113 * Gets the target appendable. 114 * 115 * @return the target appendable. 116 */ 117 public T getAppendable() { 118 return appendable; 119 } 120 121 /** 122 * Writes a portion of an array of characters to the underlying appendable. 123 * 124 * @param cbuf an array with the characters to write. 125 * @param off offset from which to start writing characters. 126 * @param len number of characters to write. 127 * @throws NullPointerException if the array is {@code null}. 128 * @throws IndexOutOfBoundsException if {@code off} or {@code len} are negative, or if {@code off + len} is greater than {@code cbuf.length}. 129 * @throws IOException If an I/O error occurs. 130 */ 131 @Override 132 public void write(final char[] cbuf, final int off, final int len) throws IOException { 133 IOUtils.checkFromIndexSize(cbuf, off, len); 134 for (int i = 0; i < len; i++) { 135 appendable.append(cbuf[off + i]); 136 } 137 } 138 139 /** 140 * Writes a character to the underlying appendable. 141 * 142 * @param c the character to write. 143 * @throws IOException If an I/O error occurs. 144 */ 145 @Override 146 public void write(final int c) throws IOException { 147 appendable.append((char) c); 148 } 149 150 /** 151 * Writes a portion of a String to the underlying appendable. 152 * 153 * @param str a string. 154 * @param off offset from which to start writing characters. 155 * @param len number of characters to write. 156 * @throws NullPointerException if the string is {@code null}. 157 * @throws IndexOutOfBoundsException if {@code off} or {@code len} are negative, or if {@code off + len} is greater than {@code str.length()}. 158 * @throws IOException If an I/O error occurs. 159 */ 160 @Override 161 public void write(final String str, final int off, final int len) throws IOException { 162 // appendable.append will add "null" for a null String; add an explicit null check 163 Objects.requireNonNull(str, "str"); 164 appendable.append(str, off, off + len); 165 } 166}