001/* 002 * Copyright 2002-2020 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.util; 018 019import java.io.ByteArrayInputStream; 020import java.io.ByteArrayOutputStream; 021import java.io.Closeable; 022import java.io.File; 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.OutputStream; 026import java.io.Reader; 027import java.io.StringWriter; 028import java.io.Writer; 029import java.nio.file.Files; 030 031import org.springframework.lang.Nullable; 032 033/** 034 * Simple utility methods for file and stream copying. All copy methods use a block size 035 * of 4096 bytes, and close all affected streams when done. A variation of the copy 036 * methods from this class that leave streams open can be found in {@link StreamUtils}. 037 * 038 * <p>Mainly for use within the framework, but also useful for application code. 039 * 040 * @author Juergen Hoeller 041 * @author Hyunjin Choi 042 * @since 06.10.2003 043 * @see StreamUtils 044 * @see FileSystemUtils 045 */ 046public abstract class FileCopyUtils { 047 048 /** 049 * The default buffer size used when copying bytes. 050 */ 051 public static final int BUFFER_SIZE = StreamUtils.BUFFER_SIZE; 052 053 054 //--------------------------------------------------------------------- 055 // Copy methods for java.io.File 056 //--------------------------------------------------------------------- 057 058 /** 059 * Copy the contents of the given input File to the given output File. 060 * @param in the file to copy from 061 * @param out the file to copy to 062 * @return the number of bytes copied 063 * @throws IOException in case of I/O errors 064 */ 065 public static int copy(File in, File out) throws IOException { 066 Assert.notNull(in, "No input File specified"); 067 Assert.notNull(out, "No output File specified"); 068 return copy(Files.newInputStream(in.toPath()), Files.newOutputStream(out.toPath())); 069 } 070 071 /** 072 * Copy the contents of the given byte array to the given output File. 073 * @param in the byte array to copy from 074 * @param out the file to copy to 075 * @throws IOException in case of I/O errors 076 */ 077 public static void copy(byte[] in, File out) throws IOException { 078 Assert.notNull(in, "No input byte array specified"); 079 Assert.notNull(out, "No output File specified"); 080 copy(new ByteArrayInputStream(in), Files.newOutputStream(out.toPath())); 081 } 082 083 /** 084 * Copy the contents of the given input File into a new byte array. 085 * @param in the file to copy from 086 * @return the new byte array that has been copied to 087 * @throws IOException in case of I/O errors 088 */ 089 public static byte[] copyToByteArray(File in) throws IOException { 090 Assert.notNull(in, "No input File specified"); 091 return copyToByteArray(Files.newInputStream(in.toPath())); 092 } 093 094 095 //--------------------------------------------------------------------- 096 // Copy methods for java.io.InputStream / java.io.OutputStream 097 //--------------------------------------------------------------------- 098 099 /** 100 * Copy the contents of the given InputStream to the given OutputStream. 101 * Closes both streams when done. 102 * @param in the stream to copy from 103 * @param out the stream to copy to 104 * @return the number of bytes copied 105 * @throws IOException in case of I/O errors 106 */ 107 public static int copy(InputStream in, OutputStream out) throws IOException { 108 Assert.notNull(in, "No InputStream specified"); 109 Assert.notNull(out, "No OutputStream specified"); 110 111 try { 112 return StreamUtils.copy(in, out); 113 } 114 finally { 115 close(in); 116 close(out); 117 } 118 } 119 120 /** 121 * Copy the contents of the given byte array to the given OutputStream. 122 * Closes the stream when done. 123 * @param in the byte array to copy from 124 * @param out the OutputStream to copy to 125 * @throws IOException in case of I/O errors 126 */ 127 public static void copy(byte[] in, OutputStream out) throws IOException { 128 Assert.notNull(in, "No input byte array specified"); 129 Assert.notNull(out, "No OutputStream specified"); 130 131 try { 132 out.write(in); 133 } 134 finally { 135 close(out); 136 } 137 } 138 139 /** 140 * Copy the contents of the given InputStream into a new byte array. 141 * Closes the stream when done. 142 * @param in the stream to copy from (may be {@code null} or empty) 143 * @return the new byte array that has been copied to (possibly empty) 144 * @throws IOException in case of I/O errors 145 */ 146 public static byte[] copyToByteArray(@Nullable InputStream in) throws IOException { 147 if (in == null) { 148 return new byte[0]; 149 } 150 151 ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE); 152 copy(in, out); 153 return out.toByteArray(); 154 } 155 156 157 //--------------------------------------------------------------------- 158 // Copy methods for java.io.Reader / java.io.Writer 159 //--------------------------------------------------------------------- 160 161 /** 162 * Copy the contents of the given Reader to the given Writer. 163 * Closes both when done. 164 * @param in the Reader to copy from 165 * @param out the Writer to copy to 166 * @return the number of characters copied 167 * @throws IOException in case of I/O errors 168 */ 169 public static int copy(Reader in, Writer out) throws IOException { 170 Assert.notNull(in, "No Reader specified"); 171 Assert.notNull(out, "No Writer specified"); 172 173 try { 174 int charCount = 0; 175 char[] buffer = new char[BUFFER_SIZE]; 176 int charsRead; 177 while ((charsRead = in.read(buffer)) != -1) { 178 out.write(buffer, 0, charsRead); 179 charCount += charsRead; 180 } 181 out.flush(); 182 return charCount; 183 } 184 finally { 185 close(in); 186 close(out); 187 } 188 } 189 190 /** 191 * Copy the contents of the given String to the given Writer. 192 * Closes the writer when done. 193 * @param in the String to copy from 194 * @param out the Writer to copy to 195 * @throws IOException in case of I/O errors 196 */ 197 public static void copy(String in, Writer out) throws IOException { 198 Assert.notNull(in, "No input String specified"); 199 Assert.notNull(out, "No Writer specified"); 200 201 try { 202 out.write(in); 203 } 204 finally { 205 close(out); 206 } 207 } 208 209 /** 210 * Copy the contents of the given Reader into a String. 211 * Closes the reader when done. 212 * @param in the reader to copy from (may be {@code null} or empty) 213 * @return the String that has been copied to (possibly empty) 214 * @throws IOException in case of I/O errors 215 */ 216 public static String copyToString(@Nullable Reader in) throws IOException { 217 if (in == null) { 218 return ""; 219 } 220 221 StringWriter out = new StringWriter(BUFFER_SIZE); 222 copy(in, out); 223 return out.toString(); 224 } 225 226 /** 227 * Attempt to close the supplied {@link Closeable}, silently swallowing any 228 * exceptions. 229 * @param closeable the {@code Closeable} to close 230 */ 231 private static void close(Closeable closeable) { 232 try { 233 closeable.close(); 234 } 235 catch (IOException ex) { 236 // ignore 237 } 238 } 239 240}