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 * http://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 */ 017package org.apache.commons.io.output; 018 019import java.io.IOException; 020import java.io.Writer; 021import java.util.Objects; 022 023/** 024 * Writer implementation that writes the data to an {@link Appendable} 025 * Object. 026 * <p> 027 * For example, can be used with a {@link StringBuilder} 028 * or {@link StringBuffer}. 029 * </p> 030 * 031 * @since 2.7 032 * @see Appendable 033 * 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 upon error 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 upon error 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 IOException upon error 083 */ 084 @Override 085 public Writer append(final CharSequence csq, final int start, final int end) throws IOException { 086 appendable.append(csq, start, end); 087 return this; 088 } 089 090 /** 091 * Closes the stream. This implementation does nothing. 092 * 093 * @throws IOException upon error 094 */ 095 @Override 096 public void close() throws IOException { 097 // noop 098 } 099 100 /** 101 * Flushes the stream. This implementation does nothing. 102 * 103 * @throws IOException upon error 104 */ 105 @Override 106 public void flush() throws IOException { 107 // noop 108 } 109 110 /** 111 * Gets the target appendable. 112 * 113 * @return the target appendable 114 */ 115 public T getAppendable() { 116 return appendable; 117 } 118 119 /** 120 * Writes a portion of an array of characters to the underlying appendable. 121 * 122 * @param cbuf an array with the characters to write 123 * @param off offset from which to start writing characters 124 * @param len number of characters to write 125 * @throws IOException upon error 126 */ 127 @Override 128 public void write(final char[] cbuf, final int off, final int len) throws IOException { 129 Objects.requireNonNull(cbuf, "cbuf"); 130 if (len < 0 || off + len > cbuf.length) { 131 throw new IndexOutOfBoundsException("Array Size=" + cbuf.length + 132 ", offset=" + off + ", length=" + len); 133 } 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 upon error 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 IOException upon error 157 */ 158 @Override 159 public void write(final String str, final int off, final int len) throws IOException { 160 // appendable.append will add "null" for a null String; add an explicit null check 161 Objects.requireNonNull(str, "str"); 162 appendable.append(str, off, off + len); 163 } 164 165}