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.BufferedInputStream;
020import java.io.BufferedOutputStream;
021import java.io.ByteArrayInputStream;
022import java.io.ByteArrayOutputStream;
023import java.io.File;
024import java.io.FileInputStream;
025import java.io.FileOutputStream;
026import java.io.IOException;
027import java.io.InputStream;
028import java.io.OutputStream;
029import java.io.Reader;
030import java.io.StringWriter;
031import java.io.Writer;
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 * @since 06.10.2003
042 * @see StreamUtils
043 * @see FileSystemUtils
044 */
045public abstract class FileCopyUtils {
046
047        /**
048         * The default buffer size used when copying bytes.
049         */
050        public static final int BUFFER_SIZE = StreamUtils.BUFFER_SIZE;
051
052
053        //---------------------------------------------------------------------
054        // Copy methods for java.io.File
055        //---------------------------------------------------------------------
056
057        /**
058         * Copy the contents of the given input File to the given output File.
059         * @param in the file to copy from
060         * @param out the file to copy to
061         * @return the number of bytes copied
062         * @throws IOException in case of I/O errors
063         */
064        public static int copy(File in, File out) throws IOException {
065                Assert.notNull(in, "No input File specified");
066                Assert.notNull(out, "No output File specified");
067
068                return copy(new BufferedInputStream(new FileInputStream(in)),
069                                new BufferedOutputStream(new FileOutputStream(out)));
070        }
071
072        /**
073         * Copy the contents of the given byte array to the given output File.
074         * @param in the byte array to copy from
075         * @param out the file to copy to
076         * @throws IOException in case of I/O errors
077         */
078        public static void copy(byte[] in, File out) throws IOException {
079                Assert.notNull(in, "No input byte array specified");
080                Assert.notNull(out, "No output File specified");
081
082                ByteArrayInputStream inStream = new ByteArrayInputStream(in);
083                OutputStream outStream = new BufferedOutputStream(new FileOutputStream(out));
084                copy(inStream, outStream);
085        }
086
087        /**
088         * Copy the contents of the given input File into a new byte array.
089         * @param in the file to copy from
090         * @return the new byte array that has been copied to
091         * @throws IOException in case of I/O errors
092         */
093        public static byte[] copyToByteArray(File in) throws IOException {
094                Assert.notNull(in, "No input File specified");
095
096                return copyToByteArray(new BufferedInputStream(new FileInputStream(in)));
097        }
098
099
100        //---------------------------------------------------------------------
101        // Copy methods for java.io.InputStream / java.io.OutputStream
102        //---------------------------------------------------------------------
103
104        /**
105         * Copy the contents of the given InputStream to the given OutputStream.
106         * Closes both streams when done.
107         * @param in the stream to copy from
108         * @param out the stream to copy to
109         * @return the number of bytes copied
110         * @throws IOException in case of I/O errors
111         */
112        public static int copy(InputStream in, OutputStream out) throws IOException {
113                Assert.notNull(in, "No InputStream specified");
114                Assert.notNull(out, "No OutputStream specified");
115
116                try {
117                        return StreamUtils.copy(in, out);
118                }
119                finally {
120                        try {
121                                in.close();
122                        }
123                        catch (IOException ex) {
124                        }
125                        try {
126                                out.close();
127                        }
128                        catch (IOException ex) {
129                        }
130                }
131        }
132
133        /**
134         * Copy the contents of the given byte array to the given OutputStream.
135         * Closes the stream when done.
136         * @param in the byte array to copy from
137         * @param out the OutputStream to copy to
138         * @throws IOException in case of I/O errors
139         */
140        public static void copy(byte[] in, OutputStream out) throws IOException {
141                Assert.notNull(in, "No input byte array specified");
142                Assert.notNull(out, "No OutputStream specified");
143
144                try {
145                        out.write(in);
146                }
147                finally {
148                        try {
149                                out.close();
150                        }
151                        catch (IOException ex) {
152                        }
153                }
154        }
155
156        /**
157         * Copy the contents of the given InputStream into a new byte array.
158         * Closes the stream when done.
159         * @param in the stream to copy from (may be {@code null} or empty)
160         * @return the new byte array that has been copied to (possibly empty)
161         * @throws IOException in case of I/O errors
162         */
163        public static byte[] copyToByteArray(InputStream in) throws IOException {
164                if (in == null) {
165                        return new byte[0];
166                }
167
168                ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
169                copy(in, out);
170                return out.toByteArray();
171        }
172
173
174        //---------------------------------------------------------------------
175        // Copy methods for java.io.Reader / java.io.Writer
176        //---------------------------------------------------------------------
177
178        /**
179         * Copy the contents of the given Reader to the given Writer.
180         * Closes both when done.
181         * @param in the Reader to copy from
182         * @param out the Writer to copy to
183         * @return the number of characters copied
184         * @throws IOException in case of I/O errors
185         */
186        public static int copy(Reader in, Writer out) throws IOException {
187                Assert.notNull(in, "No Reader specified");
188                Assert.notNull(out, "No Writer specified");
189
190                try {
191                        int charCount = 0;
192                        char[] buffer = new char[BUFFER_SIZE];
193                        int charsRead;
194                        while ((charsRead = in.read(buffer)) != -1) {
195                                out.write(buffer, 0, charsRead);
196                                charCount += charsRead;
197                        }
198                        out.flush();
199                        return charCount;
200                }
201                finally {
202                        try {
203                                in.close();
204                        }
205                        catch (IOException ex) {
206                        }
207                        try {
208                                out.close();
209                        }
210                        catch (IOException ex) {
211                        }
212                }
213        }
214
215        /**
216         * Copy the contents of the given String to the given Writer.
217         * Closes the writer when done.
218         * @param in the String to copy from
219         * @param out the Writer to copy to
220         * @throws IOException in case of I/O errors
221         */
222        public static void copy(String in, Writer out) throws IOException {
223                Assert.notNull(in, "No input String specified");
224                Assert.notNull(out, "No Writer specified");
225
226                try {
227                        out.write(in);
228                }
229                finally {
230                        try {
231                                out.close();
232                        }
233                        catch (IOException ex) {
234                        }
235                }
236        }
237
238        /**
239         * Copy the contents of the given Reader into a String.
240         * Closes the reader when done.
241         * @param in the reader to copy from (may be {@code null} or empty)
242         * @return the String that has been copied to (possibly empty)
243         * @throws IOException in case of I/O errors
244         */
245        public static String copyToString(Reader in) throws IOException {
246                if (in == null) {
247                        return "";
248                }
249
250                StringWriter out = new StringWriter();
251                copy(in, out);
252                return out.toString();
253        }
254
255}