Java tutorial
/* * Copyright (C) 2008 feilong * * 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.sunchenbin.store.feilong.core.io; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.charset.Charset; import java.util.Date; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sunchenbin.store.feilong.core.date.DateExtensionUtil; import com.sunchenbin.store.feilong.core.lang.CharsetType; import com.sunchenbin.store.feilong.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 feilong * @version 1.0.6 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.6 */ public final class IOWriteUtil { /** The Constant LOGGER. */ private static final Logger LOGGER = LoggerFactory.getLogger(IOWriteUtil.class); /** ? 10k <code>{@value}</code> */ public static final int DEFAULT_BUFFER_LENGTH = (int) (10 * FileUtils.ONE_KB); /** 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 * ?? * @see com.sunchenbin.store.feilong.core.io.IOWriteUtil#write(InputStream, OutputStream) */ public static void write(InputStream inputStream, String directoryName, String fileName) { String filePath = directoryName + "/" + fileName; FileUtil.createDirectory(directoryName); OutputStream outputStream = FileUtil.getFileOutputStream(filePath); write(inputStream, outputStream); } /** * * * <h3>:</h3> * * <blockquote> * <ul> * <li> <code>Validator.isNullOrEmpty(filePath)</code>, {@link NullPointerException}</li> * <li>?,, (?? )</li> * <li>,?{@link FileWriteMode#APPEND}?</li> * <li>? <code>charsetType</code>,{@link CharsetType#UTF8}?</li> * </ul> * </blockquote> * * @param filePath * * @param content * * @see FileWriteMode * @see CharsetType */ public static void write(String filePath, String content) { String encode = null; write(filePath, content, encode); } /** * /. * * <h3>:</h3> * * <blockquote> * <ul> * <li> <code>Validator.isNullOrEmpty(filePath)</code>, {@link NullPointerException}</li> * <li>?,, (?? )</li> * <li>,?{@link FileWriteMode#APPEND}?</li> * <li>? <code>charsetType</code>,{@link CharsetType#UTF8}?</li> * </ul> * </blockquote> * * @param filePath * * @param content * * @param encode * ?,isNullOrEmpty, {@link CharsetType#UTF8}? {@link CharsetType} * @see FileWriteMode * @see CharsetType * @see #write(String, String, String, FileWriteMode) */ public static void write(String filePath, String content, String encode) { write(filePath, content, encode, FileWriteMode.COVER);//default_fileWriteMode } /** * . * * <h3>:</h3> * * <blockquote> * <ul> * <li> <code>Validator.isNullOrEmpty(filePath)</code>, {@link NullPointerException}</li> * <li>?,, (?? )</li> * <li>,?{@link FileWriteMode#APPEND}?</li> * <li>? <code>charsetType</code>,{@link CharsetType#UTF8}?</li> * </ul> * </blockquote> * * @param filePath * * @param content * * @param charsetType * {@link CharsetType} ?,isNullOrEmpty, {@link CharsetType#UTF8}? * @param fileWriteMode * ? {@link FileWriteMode} * @see java.io.FileOutputStream#FileOutputStream(File, boolean) * @see #write(InputStream, OutputStream) * @see org.apache.commons.io.FileUtils#writeStringToFile(File, String, Charset, boolean) */ public static void write(String filePath, String content, String charsetType, FileWriteMode fileWriteMode) { if (Validator.isNullOrEmpty(filePath)) { throw new NullPointerException("filePath can't be null/empty!"); } Date beginDate = new Date(); String useEncode = Validator.isNullOrEmpty(charsetType) ? CharsetType.UTF8 : charsetType; FileWriteMode useFileWriteMode = Validator.isNullOrEmpty(fileWriteMode) ? FileWriteMode.COVER : fileWriteMode; FileUtil.createDirectoryByFilePath(filePath); InputStream inputStream = IOUtils.toInputStream(content, Charset.forName(useEncode)); OutputStream outputStream = FileUtil.getFileOutputStream(filePath, useFileWriteMode); write(inputStream, outputStream); if (LOGGER.isInfoEnabled()) { File file = new File(filePath); LOGGER.info("fileWriteMode:[{}],encode:[{}],contentLength:[{}],fileSize:[{}],absolutePath:[{}],time:{}", useFileWriteMode, useEncode, content.length(), FileUtil.getFileFormatSize(file), file.getAbsolutePath(), DateExtensionUtil.getIntervalForView(beginDate, new Date())); } } // ******************************************************************************************* /** * ?,, {@code <<>>}. * * <p span style="color:red"> * <b>(?, <code>inputStream</code>? <code>outputStream</code>).</b> * </p> * * <p> * Just write in blocks instead of copying it entirely into Java's memory first.<br> * The below basic example writes it in blocks of 10KB.<br> * This way you end up with a consistent memory usage of only 10KB instead of the complete content length.<br> * Also the enduser will start getting parts of the content much sooner. * </p> * * @param inputStream * inputStream * @param outputStream * outputStream * @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) { write(DEFAULT_BUFFER_LENGTH, inputStream, outputStream); } /** * ?,, {@code <<>>} . * * <p span style="color:red"> * <b>(?, <code>inputStream</code>? <code>outputStream</code>).</b> * </p> * * @param bufferLength * ?buffer? * @param inputStream * inputStream * @param outputStream * outputStream * @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 #writeUseNIO(int, InputStream, OutputStream) */ public static void write(int bufferLength, InputStream inputStream, OutputStream outputStream) { writeUseNIO(bufferLength, inputStream, outputStream); } /** * NIO API ?? (). * * <h3>NIO</h3> * * <blockquote> * <p> * nionew io,jdk1.4,??<br> * nio??<br> * </p> * * <p> * ??,<br> * ?,,??? ????cpu,?cpu? <br> * ? Java IO ,? IO,NIO ?? IO * </p> * * <p> * The new I/O (NIO) APIs introduced in v 1.4 provide new features and improved performance in the areas of buffer management, scalable * network and file I/O, character-set support, and regular-expression matching. The NIO APIs supplement the I/O facilities in the * java.io package. * </p> * * <p> * The NIO APIs include the following features: * </p> * * <ol> * <li>Buffers for data of primitive types</li> * <li>Character-set encoders and decoders</li> * <li>A pattern-matching facility based on Perl-style regular expressions</li> * <li>Channels, a new primitive I/O abstraction</li> * <li>A file interface that supports locks and memory mapping</li> * <li>A multiplexed, non-blocking I/O facility for writing scalable servers</li> * </ol> * </blockquote> * * <p> * As creme de la creme with regard to performance,you could use NIO {@link java.nio.channels.Channels} and {@link java.nio.ByteBuffer}. * </p> * * @param bufferLength * the buffer length * @param inputStream * the input stream * @param outputStream * the output stream * @since 1.0.8 * @since jdk1.4 */ private static void writeUseNIO(int bufferLength, InputStream inputStream, OutputStream outputStream) { Date beginDate = new Date(); ReadableByteChannel readableByteChannel = Channels.newChannel(inputStream); WritableByteChannel writableByteChannel = Channels.newChannel(outputStream); ByteBuffer byteBuffer = ByteBuffer.allocate(bufferLength); try { int loopCount = 0; int sumSize = 0; while (readableByteChannel.read(byteBuffer) != -1) { byteBuffer.flip(); sumSize += writableByteChannel.write(byteBuffer); byteBuffer.clear(); loopCount++; } if (LOGGER.isDebugEnabled()) { String formatSize = FileUtil.formatSize(sumSize); String time = DateExtensionUtil.getIntervalForView(beginDate, new Date()); LOGGER.debug("Write data over,sumSize:[{}],bufferLength:[{}],loopCount:[{}],time:{}", formatSize, bufferLength, loopCount, time); } } catch (IOException e) { throw new UncheckedIOException(e); } finally { IOUtils.closeQuietly(outputStream); IOUtils.closeQuietly(writableByteChannel); IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(readableByteChannel); } } }