/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.mcxiaoke.next.utils; import android.content.Context; import com.mcxiaoke.next.Charsets; import com.mcxiaoke.next.io.StringBuilderWriter; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.CharArrayWriter; import java.io.Closeable; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.math.BigInteger; import java.net.HttpURLConnection; import java.net.ServerSocket; import java.net.Socket; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.nio.channels.FileChannel; import java.nio.channels.Selector; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * General IO stream manipulation utilities. */ public final class IOUtils { public static final char DIR_SEPARATOR_UNIX = '/'; public static final char DIR_SEPARATOR_WINDOWS = '\\'; public static final char DIR_SEPARATOR = File.separatorChar; public static final String LINE_SEPARATOR_UNIX = "\n"; public static final String LINE_SEPARATOR_WINDOWS = "\r\n"; public static final String LINE_SEPARATOR = System.getProperty("line.separator"); public final static String FILE_EXTENSION_SEPARATOR = "."; public static final long ONE_KB = 1024; public static final BigInteger ONE_KB_BI = BigInteger.valueOf(ONE_KB); public static final BigInteger ONE_MB_BI = ONE_KB_BI.multiply(ONE_KB_BI); public static final BigInteger ONE_GB_BI = ONE_KB_BI.multiply(ONE_MB_BI); public static final BigInteger ONE_TB_BI = ONE_KB_BI.multiply(ONE_GB_BI); //----------------------------------------------------------------------- public static final BigInteger ONE_PB_BI = ONE_KB_BI.multiply(ONE_TB_BI); public static final BigInteger ONE_EB_BI = ONE_KB_BI.multiply(ONE_PB_BI); public static final long ONE_MB = ONE_KB * ONE_KB; private static final long FILE_COPY_BUFFER_SIZE = ONE_MB * 30; public static final long ONE_GB = ONE_KB * ONE_MB; public static final long ONE_TB = ONE_KB * ONE_GB; public static final long ONE_PB = ONE_KB * ONE_TB; public static final long ONE_EB = ONE_KB * ONE_PB; public static final BigInteger ONE_ZB = BigInteger.valueOf(ONE_KB).multiply(BigInteger.valueOf(ONE_EB)); // read readBytes //----------------------------------------------------------------------- public static final BigInteger ONE_YB = ONE_KB_BI.multiply(ONE_ZB); private static final int EOF = -1; private static final int DEFAULT_BUFFER_SIZE = 1024 * 8; private static final int SKIP_BUFFER_SIZE = 2048; private static final String RESERVED_CHARS = "|\\?*<\":>+[]/'"; // Allocated in the relevant skip method if necessary. /* * N.B. no need to synchronize these because: * - we don't care if the buffer is created multiple times (the data is ignored) * - we always use the same size buffer, so if it it is recreated it will still be OK * (if the buffer size were variable, we would need to sync. to ensure some other thread * did not create a smaller one) */ private static char[] SKIP_CHAR_BUFFER; private static byte[] SKIP_BYTE_BUFFER; /** * Instances should NOT be constructed in standard programming. */ private IOUtils() { } public static void close(URLConnection conn) { if (conn instanceof HttpURLConnection) { ((HttpURLConnection) conn).disconnect(); } } // read char[] //----------------------------------------------------------------------- public static void closeQuietly(Reader input) { closeQuietly((Closeable) input); } public static void closeQuietly(Writer output) { closeQuietly((Closeable) output); } public static void closeQuietly(InputStream input) { closeQuietly((Closeable) input); } public static void closeQuietly(OutputStream output) { closeQuietly((Closeable) output); } // read readString //----------------------------------------------------------------------- public static void closeQuietly(Closeable closeable) { try { if (closeable != null) { closeable.close(); } } catch (IOException ignored) { // ignore } } public static void closeQuietly(Socket sock) { if (sock != null) { try { sock.close(); } catch (IOException ignored) { // ignored } } } public static void closeQuietly(Selector selector) { if (selector != null) { try { selector.close(); } catch (IOException ignored) { // ignored } } } public static void closeQuietly(ServerSocket sock) { if (sock != null) { try { sock.close(); } catch (IOException ignored) { // ignored } } } public static byte[] readBytes(File file) throws IOException { return readBytes(new FileInputStream(file)); } public static byte[] readBytes(InputStream input) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); copy(input, output); return output.toByteArray(); } public static byte[] readBytes(InputStream input, int size) throws IOException { if (size < 0) { throw new IllegalArgumentException("Size must be equal or greater than zero: " + size); } if (size == 0) { return new byte[0]; } byte[] data = new byte[size]; int offset = 0; int readed; while (offset < size && (readed = input.read(data, offset, size - offset)) != EOF) { offset += readed; } if (offset != size) { throw new IOException("Unexpected readed size. current: " + offset + ", excepted: " + size); } return data; } public static byte[] readBytes(Reader input) throws IOException { return readBytes(input, Charset.defaultCharset()); } public static byte[] readBytes(Reader input, Charset encoding) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); copy(input, output, encoding); return output.toByteArray(); } public static byte[] readBytes(Reader input, String encoding) throws IOException { return readBytes(input, Charsets.toCharset(encoding)); } public static byte[] readBytes(URI uri) throws IOException { return IOUtils.readBytes(uri.toURL()); } // readStringList //----------------------------------------------------------------------- public static byte[] readBytes(URL url) throws IOException { URLConnection conn = url.openConnection(); try { return readBytes(conn); } finally { close(conn); } } public static byte[] readBytes(URLConnection urlConn) throws IOException { InputStream inputStream = urlConn.getInputStream(); try { return IOUtils.readBytes(inputStream); } finally { inputStream.close(); } } public static char[] readChars(InputStream is) throws IOException { return readChars(is, Charset.defaultCharset()); } public static char[] readChars(InputStream is, Charset encoding) throws IOException { CharArrayWriter output = new CharArrayWriter(); copy(is, output, encoding); return output.toCharArray(); } public static char[] readChars(InputStream is, String encoding) throws IOException { return readChars(is, Charsets.toCharset(encoding)); } public static char[] readChars(Reader input) throws IOException { CharArrayWriter sw = new CharArrayWriter(); copy(input, sw); return sw.toCharArray(); } public static String readString(InputStream input) throws IOException { return readString(input, Charset.defaultCharset()); } public static String readString(InputStream input, Charset encoding) throws IOException { StringBuilderWriter sw = new StringBuilderWriter(); copy(input, sw, encoding); return sw.toString(); } // toInputStream //----------------------------------------------------------------------- public static String readString(InputStream input, String encoding) throws IOException { return readString(input, Charsets.toCharset(encoding)); } public static String readString(Reader input) throws IOException { StringBuilderWriter sw = new StringBuilderWriter(); copy(input, sw); return sw.toString(); } public static String readString(URI uri) throws IOException { return readString(uri, Charset.defaultCharset()); } public static String readString(URI uri, Charset encoding) throws IOException { return readString(uri.toURL(), Charsets.toCharset(encoding)); } public static String readString(URI uri, String encoding) throws IOException { return readString(uri, Charsets.toCharset(encoding)); } public static String readString(URL url) throws IOException { return readString(url, Charset.defaultCharset()); } // write byte[] //----------------------------------------------------------------------- public static String readString(URL url, Charset encoding) throws IOException { InputStream inputStream = url.openStream(); try { return readString(inputStream, encoding); } finally { inputStream.close(); } } public static String readString(URL url, String encoding) throws IOException { return readString(url, Charsets.toCharset(encoding)); } public static String readString(byte[] input, String encoding) throws IOException { return new String(input, Charsets.toCharset(encoding)); } public static List<String> readStringList(Reader input) throws IOException { BufferedReader reader = new BufferedReader(input); List<String> list = new ArrayList<String>(); String line = reader.readLine(); while (line != null) { list.add(line); line = reader.readLine(); } return list; } // write char[] //----------------------------------------------------------------------- public static List<String> readStringList(InputStream input) throws IOException { return readStringList(input, Charset.defaultCharset()); } public static List<String> readStringList(InputStream input, Charset encoding) throws IOException { InputStreamReader reader = new InputStreamReader(input, Charsets.toCharset(encoding)); return readStringList(reader); } public static List<String> readStringList(InputStream input, String encoding) throws IOException { return readStringList(input, Charsets.toCharset(encoding)); } public static List<String> readStringList(String filePath, String encoding) throws IOException { return readStringList(filePath, Charsets.toCharset(encoding)); } // write CharSequence //----------------------------------------------------------------------- public static List<String> readStringList(String filePath, Charset charset) throws IOException { FileInputStream stream = new FileInputStream(filePath); return readStringList(stream, charset); } public static List<String> readStringList(File file, String encoding) throws IOException { return readStringList(file, Charsets.toCharset(encoding)); } public static List<String> readStringList(File file, Charset charset) throws IOException { FileInputStream stream = new FileInputStream(file); return readStringList(stream, charset); } public static InputStream toInputStream(CharSequence input) { return toInputStream(input, Charset.defaultCharset()); } // write String //----------------------------------------------------------------------- public static InputStream toInputStream(CharSequence input, Charset encoding) { return toInputStream(input.toString(), encoding); } public static InputStream toInputStream(CharSequence input, String encoding) throws IOException { return toInputStream(input, Charsets.toCharset(encoding)); } public static InputStream toInputStream(String input) { return toInputStream(input, Charset.defaultCharset()); } public static InputStream toInputStream(String input, Charset encoding) { return new ByteArrayInputStream(input.getBytes(Charsets.toCharset(encoding))); } // writeList //----------------------------------------------------------------------- public static InputStream toInputStream(String input, String encoding) throws IOException { byte[] bytes = input.getBytes(Charsets.toCharset(encoding)); return new ByteArrayInputStream(bytes); } public static void writeBytes(byte[] data, OutputStream output) throws IOException { if (data != null) { output.write(data); } } public static void writeBytes(byte[] data, Writer output) throws IOException { writeBytes(data, output, Charset.defaultCharset()); } public static void writeBytes(byte[] data, Writer output, Charset encoding) throws IOException { if (data != null) { output.write(new String(data, Charsets.toCharset(encoding))); } } public static void writeBytes(byte[] data, Writer output, String encoding) throws IOException { writeBytes(data, output, Charsets.toCharset(encoding)); } public static void writeChars(char[] data, Writer output) throws IOException { if (data != null) { output.write(data); } } public static void writeChars(char[] data, OutputStream output) throws IOException { writeChars(data, output, Charset.defaultCharset()); } public static void writeChars(char[] data, OutputStream output, Charset encoding) throws IOException { if (data != null) { output.write(new String(data).getBytes(Charsets.toCharset(encoding))); } } public static void writeChars(char[] data, OutputStream output, String encoding) throws IOException { writeChars(data, output, Charsets.toCharset(encoding)); } public static void writeCharSequence(CharSequence data, Writer output) throws IOException { if (data != null) { writeString(data.toString(), output); } } public static void writeCharSequence(CharSequence data, OutputStream output) throws IOException { writeCharSequence(data, output, Charset.defaultCharset()); } public static void writeCharSequence(CharSequence data, OutputStream output, Charset encoding) throws IOException { if (data != null) { writeString(data.toString(), output, encoding); } } public static void writeCharSequence(CharSequence data, OutputStream output, String encoding) throws IOException { writeCharSequence(data, output, Charsets.toCharset(encoding)); } // copy from File public static void writeString(String data, Writer output) throws IOException { if (data != null) { output.write(data); } } public static void writeString(String data, OutputStream output) throws IOException { writeString(data, output, Charset.defaultCharset()); } // copy from InputStream //----------------------------------------------------------------------- public static void writeString(String data, OutputStream output, Charset encoding) throws IOException { if (data != null) { output.write(data.getBytes(Charsets.toCharset(encoding))); } } public static void writeString(String data, OutputStream output, String encoding) throws IOException { writeString(data, output, Charsets.toCharset(encoding)); } public static void writeList(Collection<?> lines, String filePath) throws IOException { writeList(lines, filePath, Charset.defaultCharset()); } public static void writeList(Collection<?> lines, File file) throws IOException { writeList(lines, file, Charset.defaultCharset()); } public static void writeList(Collection<?> lines, String filePath, String encoding) throws IOException { writeList(lines, filePath, Charsets.toCharset(encoding)); } public static void writeList(Collection<?> lines, File file, String encoding) throws IOException { writeList(lines, file, Charsets.toCharset(encoding)); } public static void writeList(Collection<?> lines, String filePath, Charset charset) throws IOException { FileOutputStream fos = new FileOutputStream(filePath); writeList(lines, fos, charset); } public static void writeList(Collection<?> lines, File file, Charset charset) throws IOException { FileOutputStream fos = new FileOutputStream(file); writeList(lines, fos, charset); } // copy from Reader //----------------------------------------------------------------------- public static void writeList(Collection<?> lines, OutputStream output) throws IOException { writeList(lines, output, Charset.defaultCharset()); } public static void writeList(Collection<?> lines, OutputStream output, String encoding) throws IOException { writeList(lines, output, Charsets.toCharset(encoding)); } public static void writeList(Collection<?> lines, OutputStream output, Charset encoding) throws IOException { writeList(lines, output, encoding, LINE_SEPARATOR); } public static void writeList(Collection<?> lines, OutputStream output, String encoding, String lineSeparator) throws IOException { writeList(lines, output, Charsets.toCharset(encoding), lineSeparator); } public static void writeList(Collection<?> lines, OutputStream output, Charset encoding, String lineSeparator) throws IOException { if (lines == null) { return; } if (lineSeparator == null) { lineSeparator = LINE_SEPARATOR; } Charset cs = Charsets.toCharset(encoding); try { for (Object line : lines) { if (line != null) { output.write(line.toString().getBytes(cs)); } output.write(lineSeparator.getBytes(cs)); } } finally { IOUtils.closeQuietly(output); } } public static void writeList(Collection<?> lines, Writer writer) throws IOException { writeList(lines, LINE_SEPARATOR, writer); } public static void writeList(Collection<?> lines, String lineSeparator, Writer writer) throws IOException { if (lines == null) { return; } if (lineSeparator == null) { lineSeparator = LINE_SEPARATOR; } try { for (Object line : lines) { if (line != null) { writer.write(line.toString()); } writer.write(lineSeparator); } } finally { IOUtils.closeQuietly(writer); } } public static void copyLegacy(File source, File dest) throws IOException { InputStream input = null; OutputStream output = null; try { input = new FileInputStream(source); output = new FileOutputStream(dest); byte[] buf = new byte[1024]; int bytesRead; while ((bytesRead = input.read(buf)) > 0) { output.write(buf, 0, bytesRead); } } finally { IOUtils.closeQuietly(input); IOUtils.closeQuietly(output); } } // content equals //----------------------------------------------------------------------- public static void copy(File sourceFile, File destFile) throws IOException { if (!destFile.exists()) { destFile.createNewFile(); } FileChannel source = null; FileChannel destination = null; try { source = new FileInputStream(sourceFile).getChannel(); destination = new FileOutputStream(destFile).getChannel(); destination.transferFrom(source, 0, source.size()); } finally { if (source != null) { source.close(); } if (destination != null) { destination.close(); } } } public static int copy(InputStream input, OutputStream output) throws IOException { long count = copyLarge(input, output); if (count > Integer.MAX_VALUE) { return -1; } return (int) count; } public static long copyLarge(InputStream input, OutputStream output) throws IOException { return copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); } public static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException { long count = 0; int n = 0; try { while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } } finally { IOUtils.closeQuietly(input); IOUtils.closeQuietly(output); } return count; } public static long copyLarge(InputStream input, OutputStream output, long inputOffset, long length) throws IOException { return copyLarge(input, output, inputOffset, length, new byte[DEFAULT_BUFFER_SIZE]); } public static long copyLarge(InputStream input, OutputStream output, final long inputOffset, final long length, byte[] buffer) throws IOException { if (inputOffset > 0) { skipFully(input, inputOffset); } if (length == 0) { return 0; } final int bufferLength = buffer.length; int bytesToRead = bufferLength; if (length > 0 && length < bufferLength) { bytesToRead = (int) length; } int read; long totalRead = 0; try { while (bytesToRead > 0 && EOF != (read = input.read(buffer, 0, bytesToRead))) { output.write(buffer, 0, read); totalRead += read; if (length > 0) { // only adjust length if not reading to the end // Note the cast must work because buffer.length is an integer bytesToRead = (int) Math.min(length - totalRead, bufferLength); } } } finally { IOUtils.closeQuietly(input); IOUtils.closeQuietly(output); } return totalRead; } public static void copy(InputStream input, Writer output) throws IOException { copy(input, output, Charset.defaultCharset()); } public static void copy(InputStream input, Writer output, Charset encoding) throws IOException { InputStreamReader in = new InputStreamReader(input, Charsets.toCharset(encoding)); copy(in, output); } public static void copy(InputStream input, Writer output, String encoding) throws IOException { copy(input, output, Charsets.toCharset(encoding)); } public static int copy(Reader input, Writer output) throws IOException { long count = copyLarge(input, output); if (count > Integer.MAX_VALUE) { return -1; } return (int) count; } public static long copyLarge(Reader input, Writer output) throws IOException { return copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]); } public static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { long count = 0; int n = 0; while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return count; } public static long copyLarge(Reader input, Writer output, final long inputOffset, final long length) throws IOException { return copyLarge(input, output, inputOffset, length, new char[DEFAULT_BUFFER_SIZE]); } public static long copyLarge(Reader input, Writer output, final long inputOffset, final long length, char[] buffer) throws IOException { if (inputOffset > 0) { skipFully(input, inputOffset); } if (length == 0) { return 0; } int bytesToRead = buffer.length; if (length > 0 && length < buffer.length) { bytesToRead = (int) length; } int read; long totalRead = 0; try { while (bytesToRead > 0 && EOF != (read = input.read(buffer, 0, bytesToRead))) { output.write(buffer, 0, read); totalRead += read; if (length > 0) { // only adjust length if not reading to the end // Note the cast must work because buffer.length is an integer bytesToRead = (int) Math.min(length - totalRead, buffer.length); } } } finally { IOUtils.closeQuietly(input); IOUtils.closeQuietly(output); } return totalRead; } public static void copy(Reader input, OutputStream output) throws IOException { copy(input, output, Charset.defaultCharset()); } public static void copy(Reader input, OutputStream output, Charset encoding) throws IOException { OutputStreamWriter out = new OutputStreamWriter(output, Charsets.toCharset(encoding)); copy(input, out); // XXX Unless anyone is planning on rewriting OutputStreamWriter, // we have to flush here. out.flush(); } public static void copy(Reader input, OutputStream output, String encoding) throws IOException { copy(input, output, Charsets.toCharset(encoding)); } public static long skip(InputStream input, long toSkip) throws IOException { if (toSkip < 0) { throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip); } /* * N.B. no need to synchronize this because: - we don't care if the buffer is created multiple times (the data * is ignored) - we always use the same size buffer, so if it it is recreated it will still be OK (if the buffer * size were variable, we would need to sync. to ensure some other thread did not create a smaller one) */ if (SKIP_BYTE_BUFFER == null) { SKIP_BYTE_BUFFER = new byte[SKIP_BUFFER_SIZE]; } long remain = toSkip; while (remain > 0) { long n = input.read(SKIP_BYTE_BUFFER, 0, (int) Math.min(remain, SKIP_BUFFER_SIZE)); if (n < 0) { // EOF break; } remain -= n; } return toSkip - remain; } public static long skip(Reader input, long toSkip) throws IOException { if (toSkip < 0) { throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip); } /* * N.B. no need to synchronize this because: - we don't care if the buffer is created multiple times (the data * is ignored) - we always use the same size buffer, so if it it is recreated it will still be OK (if the buffer * size were variable, we would need to synch. to ensure some other thread did not create a smaller one) */ if (SKIP_CHAR_BUFFER == null) { SKIP_CHAR_BUFFER = new char[SKIP_BUFFER_SIZE]; } long remain = toSkip; while (remain > 0) { long n = input.read(SKIP_CHAR_BUFFER, 0, (int) Math.min(remain, SKIP_BUFFER_SIZE)); if (n < 0) { // EOF break; } remain -= n; } return toSkip - remain; } public static void skipFully(InputStream input, long toSkip) throws IOException { if (toSkip < 0) { throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip); } long skipped = skip(input, toSkip); if (skipped != toSkip) { throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped); } } /** * Skip the requested number of characters or fail if there are not enough left. * <p/> * This allows for the possibility that {@link Reader#skip(long)} may * not skip as many characters as requested (most likely because of reaching EOF). * * @param input stream to skip * @param toSkip the number of characters to skip * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if toSkip is negative * @throws EOFException if the number of characters skipped was incorrect * @see Reader#skip(long) * @since 2.0 */ public static void skipFully(Reader input, long toSkip) throws IOException { long skipped = skip(input, toSkip); if (skipped != toSkip) { throw new EOFException("Chars to skip: " + toSkip + " actual: " + skipped); } } /** * Read characters from an input character stream. * This implementation guarantees that it will read as many characters * as possible before giving up; this may not always be the case for * subclasses of {@link Reader}. * * @param input where to read input from * @param buffer destination * @param offset inital offset into buffer * @param length length to read, must be >= 0 * @return actual length read; may be less than requested if EOF was reached * @throws IOException if a read error occurs * @since 2.2 */ public static int read(Reader input, char[] buffer, int offset, int length) throws IOException { if (length < 0) { throw new IllegalArgumentException("Length must not be negative: " + length); } int remaining = length; try { while (remaining > 0) { int location = length - remaining; int count = input.read(buffer, offset + location, remaining); if (EOF == count) { // EOF break; } remaining -= count; } } finally { IOUtils.closeQuietly(input); } return length - remaining; } /** * Read characters from an input character stream. * This implementation guarantees that it will read as many characters * as possible before giving up; this may not always be the case for * subclasses of {@link Reader}. * * @param input where to read input from * @param buffer destination * @return actual length read; may be less than requested if EOF was reached * @throws IOException if a read error occurs * @since 2.2 */ public static int read(Reader input, char[] buffer) throws IOException { return read(input, buffer, 0, buffer.length); } /** * Read bytes from an input stream. * This implementation guarantees that it will read as many bytes * as possible before giving up; this may not always be the case for * subclasses of {@link InputStream}. * * @param input where to read input from * @param buffer destination * @param offset inital offset into buffer * @param length length to read, must be >= 0 * @return actual length read; may be less than requested if EOF was reached * @throws IOException if a read error occurs * @since 2.2 */ public static int read(InputStream input, byte[] buffer, int offset, int length) throws IOException { if (length < 0) { throw new IllegalArgumentException("Length must not be negative: " + length); } int remaining = length; try { while (remaining > 0) { int location = length - remaining; int count = input.read(buffer, offset + location, remaining); if (EOF == count) { // EOF break; } remaining -= count; } } finally { IOUtils.closeQuietly(input); } return length - remaining; } /** * Read bytes from an input stream. * This implementation guarantees that it will read as many bytes * as possible before giving up; this may not always be the case for * subclasses of {@link InputStream}. * * @param input where to read input from * @param buffer destination * @return actual length read; may be less than requested if EOF was reached * @throws IOException if a read error occurs * @since 2.2 */ public static int read(InputStream input, byte[] buffer) throws IOException { return read(input, buffer, 0, buffer.length); } /** * Read the requested number of characters or fail if there are not enough left. * <p/> * This allows for the possibility that {@link Reader#read(char[], int, int)} may * not read as many characters as requested (most likely because of reaching EOF). * * @param input where to read input from * @param buffer destination * @param offset inital offset into buffer * @param length length to read, must be >= 0 * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if length is negative * @throws EOFException if the number of characters read was incorrect * @since 2.2 */ public static void readFully(Reader input, char[] buffer, int offset, int length) throws IOException { int actual = read(input, buffer, offset, length); if (actual != length) { throw new EOFException("Length to read: " + length + " actual: " + actual); } } /** * Read the requested number of characters or fail if there are not enough left. * <p/> * This allows for the possibility that {@link Reader#read(char[], int, int)} may * not read as many characters as requested (most likely because of reaching EOF). * * @param input where to read input from * @param buffer destination * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if length is negative * @throws EOFException if the number of characters read was incorrect * @since 2.2 */ public static void readFully(Reader input, char[] buffer) throws IOException { readFully(input, buffer, 0, buffer.length); } /** * Read the requested number of bytes or fail if there are not enough left. * <p/> * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may * not read as many bytes as requested (most likely because of reaching EOF). * * @param input where to read input from * @param buffer destination * @param offset inital offset into buffer * @param length length to read, must be >= 0 * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if length is negative * @throws EOFException if the number of bytes read was incorrect * @since 2.2 */ public static void readFully(InputStream input, byte[] buffer, int offset, int length) throws IOException { int actual = read(input, buffer, offset, length); if (actual != length) { throw new EOFException("Length to read: " + length + " actual: " + actual); } } /** * Read the requested number of bytes or fail if there are not enough left. * <p/> * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may * not read as many bytes as requested (most likely because of reaching EOF). * * @param input where to read input from * @param buffer destination * @throws IOException if there is a problem reading the file * @throws IllegalArgumentException if length is negative * @throws EOFException if the number of bytes read was incorrect * @since 2.2 */ public static void readFully(InputStream input, byte[] buffer) throws IOException { readFully(input, buffer, 0, buffer.length); } /** * get an asset using ACCESS_STREAMING mode. This provides access to files that have been bundled with an * application as assets -- that is, files placed in to the "assets" directory. * * @param context * @param fileName The name of the asset to open. This name can be hierarchical. * @return */ public static String readStringFromAssets(Context context, String fileName) throws IOException { if (context == null || StringUtils.isEmpty(fileName)) { return null; } StringBuilder s = new StringBuilder(""); InputStreamReader in = new InputStreamReader(context.getResources().getAssets().open(fileName)); BufferedReader br = new BufferedReader(in); String line; while ((line = br.readLine()) != null) { s.append(line); } return s.toString(); } /** * get content from a raw resource. This can only be used with resources whose value is the name of an * asset files -- that is, it can be used to open drawable, sound, and raw resources; it will fail on string and * color resources. * * @param context * @param resId The resource identifier to open, as generated by the appt tool. * @return */ public static String readStringFromRaw(Context context, int resId) throws IOException { if (context == null) { return null; } StringBuilder s = new StringBuilder(); InputStreamReader in = new InputStreamReader(context.getResources().openRawResource(resId)); BufferedReader br = new BufferedReader(in); String line; while ((line = br.readLine()) != null) { s.append(line); } return s.toString(); } public static String readString(String filePath, Charset charset) throws IOException { return readString(new File(filePath), charset); } public static String readString(String filePath, String charsetName) throws IOException { return readString(new File(filePath), Charsets.toCharset(charsetName)); } public static String readString(File file, String charsetName) throws IOException { return readString(file, Charsets.toCharset(charsetName)); } /** * read file * * @param file file * @param charset The name of a supported {@link Charset </code>charset<code>} * @return if file not exist, return null, else return content of file * @throws IOException if an error occurs while operator BufferedReader */ public static String readString(File file, Charset charset) throws IOException { if (file == null || !file.isFile()) { return null; } StringBuilder fileContent = new StringBuilder(); BufferedReader reader = null; try { InputStreamReader is = new InputStreamReader(new FileInputStream(file), charset); reader = new BufferedReader(is); String line = null; while ((line = reader.readLine()) != null) { if (!fileContent.toString().equals("")) { fileContent.append("\r\n"); } fileContent.append(line); } reader.close(); return fileContent.toString(); } finally { closeQuietly(reader); } } public static boolean writeString(String filePath, String content) throws IOException { return writeString(filePath, content, false); } /** * write file * * @param filePath * @param content * @param append is append, if true, write to the end of file, else clear content of file and write into it * @return return true * @throws IOException if an error occurs while operator FileWriter */ public static boolean writeString(String filePath, String content, boolean append) throws IOException { return writeString(filePath != null ? new File(filePath) : null, content, append); } public static boolean writeString(File file, String content) throws IOException { return writeString(file, content, false); } public static boolean writeString(File file, String content, boolean append) throws IOException { FileWriter fileWriter = null; try { fileWriter = new FileWriter(file, append); fileWriter.write(content); fileWriter.close(); return true; } finally { closeQuietly(fileWriter); } } /** * write file * * @param filePath * @param stream * @return * @see {@link #writeStream(String, InputStream, boolean)} */ public static boolean writeStream(String filePath, InputStream stream) throws IOException { return writeStream(filePath, stream, false); } /** * write file * * @param filePath the file to be opened for writing. * @param stream the input stream * @param append if <code>true</code>, then bytes will be written to the end of the file rather than the beginning * @return return true * @throws IOException if an error occurs while operator FileOutputStream */ public static boolean writeStream(String filePath, InputStream stream, boolean append) throws IOException { return writeStream(filePath != null ? new File(filePath) : null, stream, append); } /** * write file * * @param file * @param stream * @return * @see {@link #writeStream(File, InputStream, boolean)} */ public static boolean writeStream(File file, InputStream stream) throws IOException { return writeStream(file, stream, false); } /** * write file * * @param file the file to be opened for writing. * @param stream the input stream * @param append if <code>true</code>, then bytes will be written to the end of the file rather than the beginning * @return return true * @throws IOException if an error occurs while operator FileOutputStream */ public static boolean writeStream(File file, InputStream stream, boolean append) throws IOException { OutputStream o = null; try { makeDirs(file.getAbsolutePath()); o = new FileOutputStream(file, append); byte data[] = new byte[1024]; int length = -1; while ((length = stream.read(data)) != -1) { o.write(data, 0, length); } o.flush(); return true; } finally { closeQuietly(o); closeQuietly(stream); } } public static boolean writeBytes(String filePath, byte[] data) throws IOException { return writeBytes(filePath, data, false); } public static boolean writeBytes(String filePath, byte[] data, boolean append) throws IOException { if (StringUtils.isEmpty(filePath)) { return false; } File file = new File(filePath); return writeBytes(file, data, false); } public static boolean writeBytes(File file, byte[] data) throws IOException { return writeBytes(file, data, false); } public static boolean writeBytes(File file, byte[] data, boolean append) throws IOException { OutputStream o = null; try { makeDirs(file.getAbsolutePath()); o = new FileOutputStream(file, append); o.write(data); o.flush(); return true; } finally { closeQuietly(o); } } /** * get file name from path, not include suffix * <p/> * <pre> * getFileNameWithoutExtension(null) = null * getFileNameWithoutExtension("") = "" * getFileNameWithoutExtension(" ") = " " * getFileNameWithoutExtension("abc") = "abc" * getFileNameWithoutExtension("a.mp3") = "a" * getFileNameWithoutExtension("a.b.rmvb") = "a.b" * getFileNameWithoutExtension("c:\\") = "" * getFileNameWithoutExtension("c:\\a") = "a" * getFileNameWithoutExtension("c:\\a.b") = "a" * getFileNameWithoutExtension("c:a.txt\\a") = "a" * getFileNameWithoutExtension("/home/admin") = "admin" * getFileNameWithoutExtension("/home/admin/a.txt/b.mp3") = "b" * </pre> * * @param filePath * @return file name from path, not include suffix * @see */ public static String getFileNameWithoutExtension(String filePath) { if (StringUtils.isEmpty(filePath)) { return filePath; } int extenPosi = filePath.lastIndexOf(FILE_EXTENSION_SEPARATOR); int filePosi = filePath.lastIndexOf(File.separator); if (filePosi == -1) { return (extenPosi == -1 ? filePath : filePath.substring(0, extenPosi)); } if (extenPosi == -1) { return filePath.substring(filePosi + 1); } return (filePosi < extenPosi ? filePath.substring(filePosi + 1, extenPosi) : filePath.substring(filePosi + 1)); } /** * get file name from path, include suffix * <p/> * <pre> * getFileName(null) = null * getFileName("") = "" * getFileName(" ") = " " * getFileName("a.mp3") = "a.mp3" * getFileName("a.b.rmvb") = "a.b.rmvb" * getFileName("abc") = "abc" * getFileName("c:\\") = "" * getFileName("c:\\a") = "a" * getFileName("c:\\a.b") = "a.b" * getFileName("c:a.txt\\a") = "a" * getFileName("/home/admin") = "admin" * getFileName("/home/admin/a.txt/b.mp3") = "b.mp3" * </pre> * * @param filePath * @return file name from path, include suffix */ public static String getFileName(String filePath) { if (StringUtils.isEmpty(filePath)) { return filePath; } int filePosi = filePath.lastIndexOf(File.separator); return (filePosi == -1) ? filePath : filePath.substring(filePosi + 1); } /** * get folder name from path * <p/> * <pre> * getFolderName(null) = null * getFolderName("") = "" * getFolderName(" ") = "" * getFolderName("a.mp3") = "" * getFolderName("a.b.rmvb") = "" * getFolderName("abc") = "" * getFolderName("c:\\") = "c:" * getFolderName("c:\\a") = "c:" * getFolderName("c:\\a.b") = "c:" * getFolderName("c:a.txt\\a") = "c:a.txt" * getFolderName("c:a\\b\\c\\d.txt") = "c:a\\b\\c" * getFolderName("/home/admin") = "/home" * getFolderName("/home/admin/a.txt/b.mp3") = "/home/admin/a.txt" * </pre> * * @param filePath * @return */ public static String getFolderName(String filePath) { if (StringUtils.isEmpty(filePath)) { return filePath; } int filePosi = filePath.lastIndexOf(File.separator); return (filePosi == -1) ? "" : filePath.substring(0, filePosi); } /** * get suffix of file from path * <p/> * <pre> * getFileExtension(null) = "" * getFileExtension("") = "" * getFileExtension(" ") = " " * getFileExtension("a.mp3") = "mp3" * getFileExtension("a.b.rmvb") = "rmvb" * getFileExtension("abc") = "" * getFileExtension("c:\\") = "" * getFileExtension("c:\\a") = "" * getFileExtension("c:\\a.b") = "b" * getFileExtension("c:a.txt\\a") = "" * getFileExtension("/home/admin") = "" * getFileExtension("/home/admin/a.txt/b") = "" * getFileExtension("/home/admin/a.txt/b.mp3") = "mp3" * </pre> * * @param filePath * @return */ public static String getFileExtension(String filePath) { if (StringUtils.isEmpty(filePath)) { return filePath; } int extenPosi = filePath.lastIndexOf(FILE_EXTENSION_SEPARATOR); int filePosi = filePath.lastIndexOf(File.separator); if (extenPosi == -1) { return ""; } return (filePosi >= extenPosi) ? "" : filePath.substring(extenPosi + 1); } /** * Creates the directory named by the trailing filename of this file, including the complete directory path required * to create this directory. <br/> * <br/> * <ul> * <strong>Attentions:</strong> * <li>makeDirs("C:\\Users\\Trinea") can only create users folder</li> * <li>makeFolder("C:\\Users\\Trinea\\") can create Trinea folder</li> * </ul> * * @param filePath * @return true if the necessary directories have been created or the target directory already exists, false one of * the directories can not be created. */ public static boolean makeDirs(String filePath) { String folderName = getFolderName(filePath); if (StringUtils.isEmpty(folderName)) { return false; } File folder = new File(folderName); return (folder.exists() && folder.isDirectory()) || folder.mkdirs(); } /** * Indicates if this file represents a file on the underlying file system. * * @param filePath * @return */ public static boolean isFileExist(String filePath) { if (StringUtils.isEmpty(filePath)) { return false; } File file = new File(filePath); return (file.exists() && file.isFile()); } /** * Indicates if this file represents a directory on the underlying file system. * * @param directoryPath * @return */ public static boolean isFolderExist(String directoryPath) { if (StringUtils.isEmpty(directoryPath)) { return false; } File dire = new File(directoryPath); return (dire.exists() && dire.isDirectory()); } /** * delete file or directory * <ul> * <li>if path is null or empty, return true</li> * <li>if path not exist, return true</li> * <li>if path exist, delete recursion. return true</li> * <ul> * * @param path * @return */ public static boolean delete(String path) { if (StringUtils.isEmpty(path)) { return true; } File file = new File(path); return delete(file); } public static boolean delete(File file) { if (file == null) { return true; } if (!file.exists()) { return true; } if (file.isFile()) { return file.delete(); } if (!file.isDirectory()) { return false; } for (File f : file.listFiles()) { if (f.isFile()) { f.delete(); } else if (f.isDirectory()) { delete(f); } } return file.delete(); } public static boolean isSymlink(File file) throws IOException { if (file == null) { throw new NullPointerException("File must not be null"); } File fileInCanonicalFile = null; if (file.getParent() == null) { fileInCanonicalFile = file; } else { File canonicalDir = file.getParentFile().getCanonicalFile(); fileInCanonicalFile = new File(canonicalDir, file.getName()); } return !fileInCanonicalFile.getCanonicalFile().equals(fileInCanonicalFile.getAbsoluteFile()); } private static long sizeOfDirectory(File directory) { final File[] files = directory.listFiles(); if (files == null) { return 0L; } long size = 0; for (final File file : files) { try { if (!isSymlink(file)) { size += sizeOf(file); if (size < 0) { break; } } } catch (IOException ignored) { } } return size; } public static long sizeOf(File file) { if (file == null || !file.exists()) { return 0L; } if (file.isDirectory()) { return sizeOfDirectory(file); } else { return file.length(); } } public static String byteCountToDisplaySize(BigInteger size) { String displaySize; if (size.divide(ONE_EB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = String.valueOf(size.divide(ONE_EB_BI)) + " EB"; } else if (size.divide(ONE_PB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = String.valueOf(size.divide(ONE_PB_BI)) + " PB"; } else if (size.divide(ONE_TB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = String.valueOf(size.divide(ONE_TB_BI)) + " TB"; } else if (size.divide(ONE_GB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = String.valueOf(size.divide(ONE_GB_BI)) + " GB"; } else if (size.divide(ONE_MB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = String.valueOf(size.divide(ONE_MB_BI)) + " MB"; } else if (size.divide(ONE_KB_BI).compareTo(BigInteger.ZERO) > 0) { displaySize = String.valueOf(size.divide(ONE_KB_BI)) + " KB"; } else { displaySize = String.valueOf(size) + " bytes"; } return displaySize; } public static String byteCountToDisplaySize(long size) { return byteCountToDisplaySize(BigInteger.valueOf(size)); } }