com.feilong.commons.core.io.IOWriteUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.feilong.commons.core.io.IOWriteUtil.java

Source

/*
 * Copyright (C) 2008 feilong (venusdrogon@163.com)
 *
 * Licensed 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 com.feilong.commons.core.io;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.feilong.commons.core.util.Validator;

/**
 * ???
 * 
 * <ul>
 * <li>{@link #write(InputStream, OutputStream)} ?,,  {@code <<>>}</li>
 * <li>{@link #write(String, String)} </li>
 * <li>{@link #write(InputStream, String, String)} inputStream  ?,??fileName</li>
 * <li>{@link #write(String, String, String)} /</li>
 * <li>{@link #write(String, String, String, FileWriteMode)} </li>
 * </ul>
 * 
 * ?,? {@link #write(String, String, String, FileWriteMode)}.
 *
 * @author <a href="mailto:venusdrogon@163.com"></a>
 * @version 1.0 Dec 23, 2013 10:23:23 PM
 * @see "org.springframework.util.StreamUtils"
 * @see "org.springframework.util.FileCopyUtils"
 * @see org.apache.commons.io.IOUtils
 * @since 1.0.0
 */
public final class IOWriteUtil {

    /** The Constant log. */
    private static final Logger log = LoggerFactory.getLogger(IOWriteUtil.class);

    /** Don't let anyone instantiate this class. */
    private IOWriteUtil() {
        //AssertionError?. ?????. ???.
        //see Effective Java 2nd
        throw new AssertionError("No " + getClass().getName() + " instances for you!");
    }

    /**
     * inputStream  ?( ??"/"),??fileName.
     * 
     * <h3>fileAllName ?</h3>
     * 
     * <blockquote>
     * <p>
     * {@code directoryName + "/" + fileName}
     * </p>
     * </blockquote>
     * <p>
     * .<br>
     *  ?,(?? )
     * </p>
     *
     * @param inputStream
     *            ?
     * @param directoryName
     *             ??"/"
     * @param fileName
     *            ??
     * @throws UncheckedIOException
     *             the unchecked io exception
     * @see com.feilong.commons.core.io.IOWriteUtil#write(InputStream, OutputStream)
     */
    public static void write(InputStream inputStream, String directoryName, String fileName)
            throws UncheckedIOException {
        String fileAllName = directoryName + "/" + fileName;
        // . ?,
        File file = new File(fileAllName);
        File fileParent = file.getParentFile();
        if (!fileParent.exists()) {
            fileParent.mkdirs();
        }
        OutputStream outputStream = FileUtil.getFileOutputStream(fileAllName);
        write(inputStream, outputStream);
    }

    /**
     * ?,,  {@code  <<>>} .<br>
     * <b>(? <code>inputStream</code>? <code>outputStream</code>).</b>
     *
     * @param inputStream
     *            inputStream
     * @param outputStream
     *            outputStream
     * @throws UncheckedIOException
     *             the unchecked io exception
     * @see java.io.OutputStream#write(byte[], int, int)
     * @see #write(int, InputStream, OutputStream)
     * @see org.apache.commons.io.IOUtils#copyLarge(InputStream, OutputStream)
     */
    public static void write(InputStream inputStream, OutputStream outputStream) throws UncheckedIOException {
        //Just write in blocks instead of copying it entirely into Java's memory first.
        //The below basic example writes it in blocks of 10KB.
        //This way you end up with a consistent memory usage of only 10KB instead of the complete content length. 
        //Also the enduser will start getting parts of the content much sooner.
        write(IOConstants.DEFAULT_BUFFER_LENGTH, inputStream, outputStream);
    }

    /**
     * ?,,  {@code  <<>>} .<br>
     * <b>(? <code>inputStream</code>? <code>outputStream</code>).</b>
     *
     * @param bufferLength
     *            ?buffer?
     * @param inputStream
     *            inputStream
     * @param outputStream
     *            outputStream
     * @throws UncheckedIOException
     *             the unchecked io exception
     * @see java.io.OutputStream#write(byte[], int, int)
     * @see org.apache.commons.io.IOUtils#copyLarge(InputStream, OutputStream)
     * @see <a href="http://stackoverflow.com/questions/10142409/write-an-inputstream-to-an-httpservletresponse">As creme de la creme with
     *      regard to performance, you could use NIO Channels and ByteBuffer. Create the following utility/helper method in some custom
     *      utility class,</a>
     * @see #writeUseIO(int, InputStream, OutputStream)
     * @see #writeUseNIO(int, InputStream, OutputStream)
     */
    public static void write(int bufferLength, InputStream inputStream, OutputStream outputStream)
            throws UncheckedIOException {
        writeUseNIO(bufferLength, inputStream, outputStream);
        //writeUseIO(bufferLength, inputStream, outputStream);
    }

    /**
     * NIO API ?? ().
     *
     * @param bufferLength
     *            the buffer length
     * @param inputStream
     *            the input stream
     * @param outputStream
     *            the output stream
     * @throws UncheckedIOException
     *             the unchecked io exception
     * @since 1.0.8
     */
    private static void writeUseNIO(int bufferLength, InputStream inputStream, OutputStream outputStream)
            throws UncheckedIOException {
        int i = 0;
        int sumSize = 0;
        int j = 0;

        ///2 
        //As creme de la creme with regard to performance, you could use NIO Channels and ByteBuffer. 

        ReadableByteChannel readableByteChannel = Channels.newChannel(inputStream);
        WritableByteChannel writableByteChannel = Channels.newChannel(outputStream);

        ByteBuffer byteBuffer = ByteBuffer.allocate(bufferLength);

        try {
            while (readableByteChannel.read(byteBuffer) != -1) {
                byteBuffer.flip();
                j = writableByteChannel.write(byteBuffer);
                sumSize += j;
                byteBuffer.clear();
                i++;
            }

            if (log.isDebugEnabled()) {
                log.debug("Write data over,sumSize:[{}],bufferLength:[{}],loopCount:[{}]",
                        FileUtil.formatSize(sumSize), bufferLength, i);
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        } finally {
            try {
                if (writableByteChannel != null) {
                    outputStream.close();
                    writableByteChannel.close();
                }
                if (readableByteChannel != null) {
                    inputStream.close();
                    readableByteChannel.close();
                }
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }
    }

    /**
     * IO API??.
     *
     * @param bufferLength
     *            the buffer length
     * @param inputStream
     *            the input stream
     * @param outputStream
     *            the output stream
     * @throws UncheckedIOException
     *             the unchecked io exception
     * @since 1.0.8
     * @deprecated use {@link #writeUseNIO(int, InputStream, OutputStream)}
     */
    @Deprecated
    private static void writeUseIO(int bufferLength, InputStream inputStream, OutputStream outputStream)
            throws UncheckedIOException {
        int i = 0;
        int sumSize = 0;
        int j = 0;

        byte[] bytes = new byte[bufferLength];
        try {
            //???bytes ?????? 
            // bytes  0?? 0???
            //??? -1?? bytes  
            //? bytes[0]  b[1] ?
            //? b  k ? b[0]  b[k-1] ?? b[k]  b[b.length-1]  
            // InputStream  read(b) ?read(b, 0, b.length) 
            while ((j = inputStream.read(bytes)) != -1) {

                //???
                //ClientAbortException:  java.net.SocketException: Software caused connection abort: socket write error
                outputStream.write(bytes, 0, j);
                i++;
                sumSize = sumSize + j;

                //if (log.isDebugEnabled()){
                //   log.debug(
                //               "write data,index:[{}],bufferLength:[{}],currentLoopLength:[{}],sumSize:[{}]",
                //               i,
                //               bufferLength,
                //               j,
                //               FileUtil.formatSize(sumSize));
                //}
            }
            if (log.isDebugEnabled()) {
                log.debug("write data over,sumSize:[{}],bufferLength:[{}],loopCount:[{}]",
                        FileUtil.formatSize(sumSize), bufferLength, i);
            }

            //?flush ?????? 
            outputStream.flush();
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        } finally {
            try {
                // ? ,^_^
                if (outputStream != null) {
                    outputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }
    }

    // *******************************************************************************************

    /**
     * 
     * 
     * <ul>
     * <li>?,;(?)</li>
     * <li>, , ? {@link FileWriteMode#COVER}.</li>
     * <li>?encode, {@link CharsetType#GBK}?</li>
     * </ul>
     *
     * @param filePath
     *            
     * @param content
     *            
     * @throws UncheckedIOException
     *             the unchecked io exception
     * @throws IllegalArgumentException
     *             <ul>
     *             <li>filePath,isDirectory</li>
     *             <li>filePath,!canWrite</li>
     *             </ul>
     * @see FileWriteMode
     * @see CharsetType
     */
    public static void write(String filePath, String content)
            throws UncheckedIOException, IllegalArgumentException {
        String encode = null;
        write(filePath, content, encode);
    }

    /**
     * /.
     * 
     * <ul>
     * <li>?,;(?)</li>
     * <li>, , ? {@link FileWriteMode#COVER}.</li>
     * </ul>
     *
     * @param filePath
     *            
     * @param content
     *            
     * @param encode
     *            ?,isNullOrEmpty, {@link CharsetType#GBK}? {@link CharsetType}
     * @throws UncheckedIOException
     *             the unchecked io exception
     * @throws IllegalArgumentException
     *             <ul>
     *             <li>filePath,isDirectory</li>
     *             <li>filePath,!canWrite</li>
     *             </ul>
     * @see FileWriteMode
     * @see CharsetType
     * @see #write(String, String, String, FileWriteMode)
     */
    public static void write(String filePath, String content, String encode)
            throws UncheckedIOException, IllegalArgumentException {
        write(filePath, content, encode, FileWriteMode.COVER);
    }

    /**
     * .
     * 
     * <ul>
     * <li>?,, (?? )</li>
     * <li>,?  {@link FileWriteMode#APPEND}??</li>
     * </ul>
     *
     * @param filePath
     *            
     * @param content
     *            
     * @param encode
     *            ?,isNullOrEmpty, {@link CharsetType#GBK}? {@link CharsetType}
     * @param fileWriteMode
     *            ?
     * @throws UncheckedIOException
     *             the unchecked io exception
     * @throws IllegalArgumentException
     *             <ul>
     *             <li>filePath,isDirectory</li>
     *             <li>filePath,!canWrite</li>
     *             </ul>
     * @see FileWriteMode
     * @see CharsetType
     * @see com.feilong.commons.core.io.FileUtil#cascadeMkdirs(String)
     * @see java.io.FileOutputStream#FileOutputStream(File, boolean)
     */
    public static void write(String filePath, String content, String encode, FileWriteMode fileWriteMode)
            throws UncheckedIOException, IllegalArgumentException {

        if (Validator.isNullOrEmpty(encode)) {
            encode = CharsetType.GBK;
        }

        // **************************************************************************8
        File file = FileUtil.cascadeMkdirs(filePath);

        boolean append = (fileWriteMode == FileWriteMode.APPEND);

        try {
            OutputStream outputStream = new FileOutputStream(file, append);
            Writer outputStreamWriter = new OutputStreamWriter(outputStream, encode);

            Writer writer = new PrintWriter(outputStreamWriter);
            writer.write(content);
            writer.close();

            if (log.isInfoEnabled()) {
                log.info("fileWriteMode:[{}],contentLength:[{}],encode:[{}],fileSize:[{}],absolutePath:[{}]",
                        fileWriteMode, content.length(), encode, FileUtil.getFileFormatSize(file),
                        file.getAbsolutePath());
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}