All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.landawn.abacus.util.IOUtil Maven / Gradle / Ivy

There is a newer version: 1.10.1
Show newest version
/*
 * Copyright (c) 2015, Haiyang Li.
 * 
 * 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.landawn.abacus.util;

import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
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.RandomAccessFile;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.charset.Charset;
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import com.landawn.abacus.exception.UncheckedIOException;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.util.function.Consumer;

/**
 *
 * @author Haiyang Li
 *
 * @version $Revision: 0.8 $
 */
public final class IOUtil {
    private static final Logger logger = LoggerFactory.getLogger(IOUtil.class);

    static final int DEFAULT_QUEUE_SIZE_FOR_ROW_PARSER = 1024;

    // ...
    public static final String PATH_SEPARATOR = N.PATH_SEPARATOR;
    public static final String FILE_SEPARATOR = N.FILE_SEPARATOR;
    public static final String LINE_SEPARATOR = N.LINE_SEPARATOR;

    // ... 
    public static final int EOF = -1;

    // ...
    private static final String ZIP = ".zip";
    private static final String GZ = ".gz";

    /**
     * The file copy buffer size (32 MB)
     */
    private static final long FILE_COPY_BUFFER_SIZE = (1024 * 1024) * 32;

    static final Method stringEncodeMethod;
    static final Method stringDecodeMethod;

    static {
        Method encodeMethod = null;
        Method decodeMethod = null;

        try {
            Class cls = RefUtil.forClass("java.lang.StringCoding");
            Method enMethod = RefUtil.getDeclaredMethod(cls, "encode", Charset.class, char[].class, int.class, int.class);
            Method deMethod = RefUtil.getDeclaredMethod(cls, "decode", Charset.class, byte[].class, int.class, int.class);

            if (enMethod != null && deMethod != null) {
                enMethod.setAccessible(true);
                deMethod.setAccessible(true);

                char[] chars = "abc".toCharArray();
                byte[] bytes = RefUtil.invokeMethod(enMethod, Charsets.DEFAULT, chars, 1, 1);
                char[] chars2 = RefUtil.invokeMethod(deMethod, Charsets.DEFAULT, bytes, 0, bytes.length);

                if (chars2.length == 1 && chars2[0] == 'b') {
                    encodeMethod = enMethod;
                    decodeMethod = deMethod;
                }
            }

        } catch (Throwable e) {
            // e.printStackTrace();
            // ignore
        }

        stringEncodeMethod = encodeMethod;
        stringDecodeMethod = decodeMethod;
    }

    /**
     * Constructor for FileUtil.
     */
    private IOUtil() {
        // no instance;
    }

    /**
     * Returns the disk size of the volume which holds the working directory.
     * 

* Identical to: *

     * freeSpaceKb(new File(".").getAbsolutePath())
     * 
* @return the amount of free drive space on the drive or volume in kilobytes * @throws IllegalStateException if an error occurred in initialisation * @throws UncheckedIOException if an error occurs when finding the free space */ public static long freeDiskSpaceKb() { try { return FileSystemUtil.freeSpaceKb(); } catch (IOException e) { throw new UncheckedIOException(e); } } /** * Returns the disk size of the volume which holds the working directory. *

* Identical to: *

     * freeSpaceKb(new File(".").getAbsolutePath())
     * 
* @param timeout The timeout amount in milliseconds or no timeout if the value * is zero or less * @return the amount of free drive space on the drive or volume in kilobytes * @throws IllegalStateException if an error occurred in initialisation * @throws UncheckedIOException if an error occurs when finding the free space */ public static long freeDiskSpaceKb(final long timeout) { try { return FileSystemUtil.freeSpaceKb(timeout); } catch (IOException e) { throw new UncheckedIOException(e); } } //----------------------------------------------------------------------- /** * Returns the free space on a drive or volume in kilobytes by invoking * the command line. *
     * FileSystemUtils.freeSpaceKb("C:");       // Windows
     * FileSystemUtils.freeSpaceKb("/volume");  // *nix
     * 
* The free space is calculated via the command line. * It uses 'dir /-c' on Windows, 'df -kP' on AIX/HP-UX and 'df -k' on other Unix. *

* In order to work, you must be running Windows, or have a implementation of * Unix df that supports GNU format when passed -k (or -kP). If you are going * to rely on this code, please check that it works on your OS by running * some simple tests to compare the command line with the output from this class. * If your operating system isn't supported, please raise a JIRA call detailing * the exact result from df -k and as much other detail as possible, thanks. * * @param path the path to get free space for, not null, not empty on Unix * @return the amount of free drive space on the drive or volume in kilobytes * @throws IllegalArgumentException if the path is invalid * @throws IllegalStateException if an error occurred in initialisation * @throws UncheckedIOException if an error occurs when finding the free space */ public static long freeDiskSpaceKb(final String path) { try { return FileSystemUtil.freeSpaceKb(path); } catch (IOException e) { throw new UncheckedIOException(e); } } /** * Returns the free space on a drive or volume in kilobytes by invoking * the command line. *

     * FileSystemUtils.freeSpaceKb("C:");       // Windows
     * FileSystemUtils.freeSpaceKb("/volume");  // *nix
     * 
* The free space is calculated via the command line. * It uses 'dir /-c' on Windows, 'df -kP' on AIX/HP-UX and 'df -k' on other Unix. *

* In order to work, you must be running Windows, or have a implementation of * Unix df that supports GNU format when passed -k (or -kP). If you are going * to rely on this code, please check that it works on your OS by running * some simple tests to compare the command line with the output from this class. * If your operating system isn't supported, please raise a JIRA call detailing * the exact result from df -k and as much other detail as possible, thanks. * * @param path the path to get free space for, not null, not empty on Unix * @param timeout The timeout amount in milliseconds or no timeout if the value * is zero or less * @return the amount of free drive space on the drive or volume in kilobytes * @throws IllegalArgumentException if the path is invalid * @throws IllegalStateException if an error occurred in initialisation * @throws UncheckedIOException if an error occurs when finding the free space */ public static long freeDiskSpaceKb(final String path, final long timeout) { try { return FileSystemUtil.freeSpaceKb(path, timeout); } catch (IOException e) { throw new UncheckedIOException(e); } } public static int parseInt(final char[] cbuf, final int offset, final int len) { return parseInt(cbuf, offset, len, 10); } /** * Refer to Integer.parseInt(String); * * @param cbuf * @param offset * @param len * @param radix * @return * @throws NumberFormatException */ // It's copied from OpenJDK 1.7 on 3/9/205 /* * Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ public static int parseInt(final char[] cbuf, final int offset, final int len, final int radix) throws NumberFormatException { if (offset < 0 || len < 0) { throw new IllegalArgumentException("'offset' and 'len' can't be negative"); } if (radix < Character.MIN_RADIX) { throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX"); } if (radix > Character.MAX_RADIX) { throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX"); } if (len == 0 || (N.isNullOrEmpty(cbuf) && offset == 0)) { return 0; } int result = 0; boolean negative = false; int limit = -Integer.MAX_VALUE; int multmin; int digit; int endIndex = offset + len; int i = offset; final char firstChar = cbuf[offset]; if (firstChar < '0') { // Possible leading "+" or "-" if (firstChar == '-') { negative = true; limit = Integer.MIN_VALUE; } else if (firstChar != '+') { throw new NumberFormatException(String.valueOf(cbuf, offset, len)); } if (len == 1) { throw new NumberFormatException(String.valueOf(cbuf, offset, len)); } i++; } multmin = limit / radix; while (i < endIndex) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit(cbuf[i++], radix); if (digit < 0) { throw new NumberFormatException(String.valueOf(cbuf, offset, len)); } if (result < multmin) { throw new NumberFormatException(String.valueOf(cbuf, offset, len)); } result *= radix; if (result < limit + digit) { throw new NumberFormatException(String.valueOf(cbuf, offset, len)); } result -= digit; } return negative ? result : -result; } public static long parseLong(final char[] cbuf, final int offset, final int len) { return parseLong(cbuf, offset, len, 10); } /** * Refer to Long.parseLong(String); * * @param cbuf * @param offset * @param len * @param radix * @return * @throws NumberFormatException */ // It's copied from OpenJDK 1.7 on 3/9/205 /* * Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ public static long parseLong(final char[] cbuf, final int offset, final int len, final int radix) throws NumberFormatException { if (offset < 0 || len < 0) { throw new IllegalArgumentException("'offset' and 'len' can't be negative"); } if (radix < Character.MIN_RADIX) { throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX"); } if (radix > Character.MAX_RADIX) { throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX"); } if (len == 0 || (N.isNullOrEmpty(cbuf) && offset == 0)) { return 0; } long result = 0; boolean negative = false; long limit = -Long.MAX_VALUE; long multmin; int digit; int endIndex = offset + len; int i = offset; final char lastChar = cbuf[offset + len - 1]; if (lastChar == 'l' || lastChar == 'L') { if (len == 1) { throw new NumberFormatException(String.valueOf(cbuf, offset, len)); } endIndex = endIndex - 1; } final char firstChar = cbuf[offset]; if (firstChar < '0') { // Possible leading "+" or "-" if (firstChar == '-') { negative = true; limit = Long.MIN_VALUE; } else if (firstChar != '+') { throw new NumberFormatException(String.valueOf(cbuf, offset, len)); } if (len == 1) { throw new NumberFormatException(String.valueOf(cbuf, offset, len)); } i++; } multmin = limit / radix; while (i < endIndex) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit(cbuf[i++], radix); if (digit < 0) { throw new NumberFormatException(String.valueOf(cbuf, offset, len)); } if (result < multmin) { throw new NumberFormatException(String.valueOf(cbuf, offset, len)); } result *= radix; if (result < limit + digit) { throw new NumberFormatException(String.valueOf(cbuf, offset, len)); } result -= digit; } return negative ? result : -result; } public static byte[] chars2Bytes(final char[] chars) { return chars2Bytes(chars, Charsets.DEFAULT); } public static byte[] chars2Bytes(final char[] chars, final Charset charset) { return chars2Bytes(chars, 0, chars.length, charset); } public static byte[] chars2Bytes(final char[] chars, final int offset, final int len, Charset charset) { charset = charset == null ? Charsets.DEFAULT : charset; if (stringEncodeMethod == null) { return new String(chars, offset, len).getBytes(charset); } else { return RefUtil.invokeMethod(stringEncodeMethod, charset, chars, offset, len); } } public static char[] bytes2Chars(final byte[] bytes) { return bytes2Chars(bytes, Charsets.DEFAULT); } public static char[] bytes2Chars(final byte[] bytes, final Charset charset) { return bytes2Chars(bytes, 0, bytes.length, charset); } public static char[] bytes2Chars(final byte bytes[], final int offset, final int len, Charset charset) { charset = charset == null ? Charsets.DEFAULT : charset; if (stringDecodeMethod == null) { return new String(bytes, offset, len, charset).toCharArray(); } else { return RefUtil.invokeMethod(stringDecodeMethod, charset, bytes, offset, len); } } public static InputStream string2InputStream(final String str) { return string2InputStream(str, Charsets.DEFAULT); } public static InputStream string2InputStream(final String str, Charset charset) { if (str == null) { throw new IllegalArgumentException("The input String can't be null."); } charset = charset == null ? Charsets.DEFAULT : charset; return new ByteArrayInputStream(str.getBytes(charset)); } public static Reader string2Reader(final String str) { if (str == null) { throw new IllegalArgumentException("The input String can't be null."); } return new StringReader(str); } public static Writer stringBuilder2Writer(final StringBuilder sb) { if (sb == null) { throw new IllegalArgumentException("The input StringBuilder can't be null."); } return new StringWriter(sb); } public static byte[] readBytes(final File file) { return readBytes(file, 0, Integer.MAX_VALUE); } public static byte[] readBytes(final File file, final long offset, final int maxLen) { final Holder outputZipFile = new Holder<>(); InputStream is = null; try { is = openFile(outputZipFile, file); return readBytes(is, offset, maxLen); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(is); close(outputZipFile.value()); } } public static byte[] readBytes(final InputStream is) { return readBytes(is, 0, Integer.MAX_VALUE); } public static byte[] readBytes(final InputStream is, final long offset, final int maxLen) { if (maxLen == 0) { return N.EMPTY_BYTE_ARRAY; } if (offset > 0) { if (skip(is, offset) < offset) { return N.EMPTY_BYTE_ARRAY; } } ByteArrayOutputStream os = null; final byte[] buf = ObjectFactory.createByteArrayBuffer(); final int bufLength = buf.length; int totalCount = 0; int count = 0; try { while (totalCount < maxLen && EOF != (count = read(is, buf, 0, Math.min(maxLen - totalCount, bufLength)))) { if (count == bufLength && count < maxLen) { if (os == null) { os = ObjectFactory.createByteArrayOutputStream(); } } if (os != null) { os.write(buf, 0, count); } totalCount += count; } return os == null ? (totalCount <= 0 ? N.EMPTY_BYTE_ARRAY : N.copyOfRange(buf, 0, totalCount)) : os.toByteArray(); } catch (IOException e) { throw new UncheckedIOException(e); } finally { ObjectFactory.recycle(buf); ObjectFactory.recycle(os); } } public static char[] readChars(final File file) { return readChars(file, 0, Integer.MAX_VALUE); } public static char[] readChars(final File file, final long offset, final int maxLen) { return readChars(file, 0, maxLen, Charsets.DEFAULT); } public static char[] readChars(final File file, final long offset, final int maxLen, final Charset encoding) { final Holder outputZipFile = new Holder<>(); InputStream is = null; try { is = openFile(outputZipFile, file); return readChars(is, offset, maxLen, encoding); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(is); close(outputZipFile.value()); } } public static char[] readChars(final InputStream is) { return readChars(is, 0, Integer.MAX_VALUE); } public static char[] readChars(final InputStream is, final long offset, final int maxLen) { return readChars(is, 0, maxLen, Charsets.DEFAULT); } public static char[] readChars(final InputStream is, final long offset, final int maxLen, Charset encoding) { encoding = encoding == null ? Charsets.DEFAULT : encoding; Reader reader = null; // try { reader = createReader(is, encoding); return readChars(reader, offset, maxLen); // } finally { // // close(reader); // } } public static char[] readChars(final Reader reader) { return readChars(reader, 0, Integer.MAX_VALUE); } public static char[] readChars(final Reader reader, final long offset, final int maxLen) { if (maxLen == 0) { return N.EMPTY_CHAR_ARRAY; } if (offset > 0) { if (skip(reader, offset) < offset) { return N.EMPTY_CHAR_ARRAY; } } StringBuilder sb = null; final char[] buf = ObjectFactory.createCharArrayBuffer(); final int bufLength = buf.length; int totalCount = 0; int count = 0; try { while (totalCount < maxLen && EOF != (count = read(reader, buf, 0, Math.min(maxLen - totalCount, bufLength)))) { if (count == bufLength && count < maxLen) { if (sb == null) { sb = ObjectFactory.createStringBuilder(); } } if (sb != null) { sb.append(buf, 0, count); } totalCount += count; } if (sb == null) { return totalCount <= 0 ? N.EMPTY_CHAR_ARRAY : N.copyOfRange(buf, 0, totalCount); } else { final char[] a = new char[totalCount]; sb.getChars(0, totalCount, a, 0); return a; } } catch (IOException e) { throw new UncheckedIOException(e); } finally { ObjectFactory.recycle(buf); ObjectFactory.recycle(sb); } } public static String readString(final File file) { return readString(file, 0, Integer.MAX_VALUE); } public static String readString(final File file, final long offset, final int maxLen) { return readString(file, offset, maxLen, Charsets.DEFAULT); } public static String readString(final File file, final long offset, final int maxLen, final Charset encoding) { final char[] chs = readChars(file, offset, maxLen, encoding); return N.isNullOrEmpty(chs) ? N.EMPTY_STRING : N.newString(chs, true); } public static String readString(final InputStream is) { return readString(is, 0, Integer.MAX_VALUE); } public static String readString(final InputStream is, final long offset, final int maxLen) { return readString(is, offset, maxLen, Charsets.DEFAULT); } public static String readString(final InputStream is, final long offset, final int maxLen, final Charset encoding) { final char[] chs = readChars(is, offset, maxLen, encoding); return N.isNullOrEmpty(chs) ? N.EMPTY_STRING : N.newString(chs, true); } public static String readString(final Reader reader) { return readString(reader, 0, Integer.MAX_VALUE); } public static String readString(final Reader reader, final long offset, final int maxLen) { final char[] chs = readChars(reader, offset, maxLen); return N.isNullOrEmpty(chs) ? N.EMPTY_STRING : N.newString(chs, true); } public static String readLine(final File file) { return readLine(file, 0); } public static String readLine(final File file, final int lineIndex) { return readLine(file, lineIndex, Charsets.DEFAULT); } public static String readLine(final File file, final int lineIndex, final Charset encoding) { final Holder outputZipFile = new Holder<>(); InputStream is = null; try { is = openFile(outputZipFile, file); return readLine(is, lineIndex, encoding); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(is); close(outputZipFile.value()); } } public static String readLine(final InputStream is) { return readLine(is, 0); } public static String readLine(final InputStream is, final int lineIndex) { return readLine(is, lineIndex, Charsets.DEFAULT); } public static String readLine(final InputStream is, final int lineIndex, final Charset encoding) { return readLine(createReader(is, encoding), lineIndex); } public static String readLine(final Reader reader) { return readLine(reader, 0); } public static String readLine(final Reader reader, int lineIndex) { final BufferedReader br = reader instanceof BufferedReader ? (BufferedReader) reader : ObjectFactory.createBufferedReader(reader); try { if (lineIndex == 0) { return br.readLine(); } else { while (lineIndex-- > 0 && br.readLine() != null) { } return br.readLine(); } } catch (IOException e) { throw new UncheckedIOException(e); } finally { if (br != reader) { ObjectFactory.recycle(br); } } } public static List readLines(final File file) { return readLines(file, 0, Integer.MAX_VALUE); } public static List readLines(final File file, final int offset, final int count) { return readLines(file, offset, count, Charsets.DEFAULT); } public static List readLines(final File file, final int offset, final int count, final Charset encoding) { final Holder outputZipFile = new Holder<>(); InputStream is = null; try { is = openFile(outputZipFile, file); return readLines(is, offset, count, encoding); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(is); close(outputZipFile.value()); } } public static List readLines(final InputStream is) { return readLines(is, 0, Integer.MAX_VALUE); } public static List readLines(final InputStream is, final int offset, final int count) { return readLines(is, offset, count, Charsets.DEFAULT); } public static List readLines(final InputStream is, final int offset, final int count, final Charset encoding) { return readLines(createReader(is, encoding), offset, count); } private static InputStreamReader createReader(final InputStream is, final Charset encoding) { return encoding == null ? new InputStreamReader(is, Charsets.DEFAULT) : new InputStreamReader(is, encoding); } public static List readLines(final Reader reader) { return readLines(reader, 0, Integer.MAX_VALUE); } public static List readLines(final Reader reader, int offset, int count) { final List res = new ArrayList<>(); final BufferedReader br = reader instanceof BufferedReader ? (BufferedReader) reader : ObjectFactory.createBufferedReader(reader); try { while (offset-- > 0 && br.readLine() != null) { } String line = null; while (count-- > 0 && (line = br.readLine()) != null) { res.add(line); } } catch (IOException e) { throw new UncheckedIOException(e); } finally { if (br != reader) { ObjectFactory.recycle(br); } } return res; } /** * Returns an Iterator for the lines in a File using the default encoding for the VM. * * @param file the file to open for input, must not be {@code null} * @return an Iterator of the lines in the file, never {@code null} * @throws UncheckedIOException in case of an I/O error (file closed) * @see #lineIterator(File, Charset) */ public static LineIterator lineIterator(final File file) { return lineIterator(file, Charsets.DEFAULT); } /** * Returns an Iterator for the lines in a File. *

* This method opens an InputStream for the file. * When you have finished with the iterator you should close the stream * to free internal resources. This can be done by calling the * {@link LineIterator#close()} or * {@link IOUtil#closeQuietly(LineIterator)} method. *

* The recommended usage pattern is: *

     * LineIterator it = FileUtils.lineIterator(file, "UTF-8");
     * try {
     *   while (it.hasNext()) {
     *     String line = it.nextLine();
     *     /// do something with line
     *   }
     * } finally {
     *   closeQuietly(iterator);
     * }
     * 
*

* If an exception occurs during the creation of the iterator, the * underlying stream is closed. * * @param file the file to open for input, must not be {@code null} * @param encoding the encoding to use, {@code null} means platform default * @return an Iterator of the lines in the file, never {@code null} * @throws UncheckedIOException in case of an I/O error (file closed) */ public static LineIterator lineIterator(final File file, final Charset encoding) { InputStream in = null; try { in = new FileInputStream(file); return lineIterator(in, encoding); } catch (final IOException ex) { closeQuietly(in); throw new UncheckedIOException(ex); } catch (final RuntimeException ex) { closeQuietly(in); throw ex; } } public static LineIterator lineIterator(final InputStream input) { return lineIterator(input, null); } /** * Returns an Iterator for the lines in an InputStream, using * the character encoding specified (or default encoding if null). *

* LineIterator holds a reference to the open * InputStream specified here. When you have finished with * the iterator you should close the stream to free internal resources. * This can be done by closing the stream directly, or by calling * {@link LineIterator#close()} or {@link IOUtil#closeQuietly(LineIterator)}. *

* The recommended usage pattern is: *

     * try {
     *   LineIterator it = lineIterator(stream, charset);
     *   while (it.hasNext()) {
     *     String line = it.nextLine();
     *     /// do something with line
     *   }
     * } finally {
     *   closeQuietly(stream);
     * }
     * 
* * @param input the InputStream to read from, not null * @param encoding the encoding to use, null means platform default * @return an Iterator of the lines in the reader, never null * @throws IllegalArgumentException if the input is null * @throws UncheckedIOException if an I/O error occurs, such as if the encoding is invalid */ public static LineIterator lineIterator(final InputStream input, final Charset encoding) { return new LineIterator(createReader(input, encoding)); } // lineIterator //----------------------------------------------------------------------- /** * Returns an Iterator for the lines in a Reader. *

* LineIterator holds a reference to the open * Reader specified here. When you have finished with the * iterator you should close the reader to free internal resources. * This can be done by closing the reader directly, or by calling * {@link LineIterator#close()} or {@link IOUtil#closeQuietly(LineIterator)}. *

* The recommended usage pattern is: *

     * try {
     *   LineIterator it = lineIterator(reader);
     *   while (it.hasNext()) {
     *     String line = it.nextLine();
     *     /// do something with line
     *   }
     * } finally {
     *   closeQuietly(reader);
     * }
     * 
* * @param reader the Reader to read from, not null * @return an Iterator of the lines in the reader, never null * @throws IllegalArgumentException if the reader is null */ public static LineIterator lineIterator(final Reader reader) { return new LineIterator(reader); } /** * * @param file * @param buf * @param off the start offset in array b at which the data is written. * @param len * @return */ public static int read(final File file, final byte[] buf, final int off, final int len) { InputStream is = null; try { is = new FileInputStream(file); return read(is, buf, off, len); } catch (IOException e) { throw new UncheckedIOException(e); } finally { closeQuietly(is); } } /** * * @param is * @param buf * @param off the start offset in array b at which the data is written. * @param len * @return * @throws IOException */ public static int read(final InputStream is, final byte[] buf, final int off, final int len) throws IOException { if ((off < 0) || (off > buf.length) || (len < 0) || ((off + len) > buf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } if (len == 0) { return 0; } int n = is.read(buf, off, len); if (n < 0 || n == len) { return n; } while (n < len) { int n1 = is.read(buf, off + n, len - n); if (n1 < 0) { break; } n += n1; } return n; } /** * * @param file * @param buf * @param off the start offset in array b at which the data is written. * @param len * @return */ public static int read(final File file, final char[] buf, final int off, final int len) { Reader reader = null; try { reader = new FileReader(file); return read(reader, buf, off, len); } catch (IOException e) { throw new UncheckedIOException(e); } finally { closeQuietly(reader); } } /** * * @param reader * @param buf * @param off the start offset in array b at which the data is written. * @param len * @return * @throws IOException */ public static int read(final Reader reader, final char[] buf, final int off, final int len) throws IOException { if ((off < 0) || (off > buf.length) || (len < 0) || ((off + len) > buf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } if (len == 0) { return 0; } int n = reader.read(buf, off, len); if (n < 0 || n == len) { return n; } while (n < len) { int n1 = reader.read(buf, off + n, len - n); if (n1 < 0) { break; } n += n1; } return n; } public static void writeLine(final File file, final Object obj) { Writer writer = null; try { writer = new FileWriter(file); writeLine(writer, obj); writer.flush(); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(writer); } } public static void writeLine(final OutputStream os, final Object obj) { writeLine(os, obj, false); } public static void writeLine(final OutputStream os, final Object obj, final boolean flush) { writeLine(new OutputStreamWriter(os), obj, flush); } public static void writeLine(final Writer writer, final Object obj) { writeLine(writer, obj, false); } public static void writeLine(final Writer writer, final Object obj, final boolean flush) { try { if (obj == null) { writer.write(N.NULL_CHAR_ARRAY); } else { writer.write(obj.toString()); } writer.write(N.LINE_SEPARATOR); if (flush) { writer.flush(); } } catch (IOException e) { throw new UncheckedIOException(e); } } public static void writeLines(final File file, final Object[] lines) { writeLines(file, lines, 0, lines.length); } public static void writeLines(final File file, final Object[] lines, final int offset, final int count) { Writer writer = null; try { writer = new FileWriter(file); writeLines(writer, lines, offset, count); writer.flush(); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(writer); } } public static void writeLines(final OutputStream os, final Object[] lines) { writeLines(os, lines, false); } public static void writeLines(final OutputStream os, final Object[] lines, final boolean flush) { writeLines(os, lines, 0, lines.length, flush); } public static void writeLines(final OutputStream os, final Object[] lines, final int offset, final int count) { writeLines(os, lines, offset, count, false); } public static void writeLines(final OutputStream os, final Object[] lines, final int offset, final int count, final boolean flush) { writeLines(new OutputStreamWriter(os), lines, offset, count, flush); } public static void writeLines(final Writer writer, final Object[] lines) { writeLines(writer, lines, false); } public static void writeLines(final Writer writer, final Object[] lines, final boolean flush) { writeLines(writer, lines, 0, lines.length, flush); } public static void writeLines(final Writer writer, final Object[] lines, final int offset, final int count) { writeLines(writer, lines, offset, count, false); } public static void writeLines(final Writer writer, final Object[] lines, final int offset, int count, final boolean flush) { boolean isBufferedWriter = writer instanceof BufferedWriter || writer instanceof java.io.BufferedWriter; final Writer bw = isBufferedWriter ? writer : ObjectFactory.createBufferedWriter(writer); try { int lineNum = 0; for (Object line : lines) { if (lineNum++ >= offset) { if (line == null) { writer.write(N.NULL_CHAR_ARRAY); } else { writer.write(line.toString()); } writer.write(N.LINE_SEPARATOR); count--; } if (count <= 0) { break; } } if (flush || !isBufferedWriter) { bw.flush(); } } catch (IOException e) { throw new UncheckedIOException(e); } finally { if (!isBufferedWriter) { ObjectFactory.recycle((BufferedWriter) bw); } } } public static void writeLines(final File file, final Collection lines) { writeLines(file, lines, 0, lines.size()); } public static void writeLines(final File file, final Collection lines, final int offset, final int count) { Writer writer = null; try { writer = new FileWriter(file); writeLines(writer, lines, offset, count); writer.flush(); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(writer); } } public static void writeLines(final OutputStream os, final Collection lines) { writeLines(os, lines, false); } public static void writeLines(final OutputStream os, final Collection lines, final boolean flush) { writeLines(os, lines, 0, lines.size(), flush); } public static void writeLines(final OutputStream os, final Collection lines, final int offset, final int count) { writeLines(os, lines, offset, count, false); } public static void writeLines(final OutputStream os, final Collection lines, final int offset, final int count, final boolean flush) { writeLines(new OutputStreamWriter(os), lines, offset, count, flush); } public static void writeLines(final Writer writer, final Collection lines) { writeLines(writer, lines, false); } public static void writeLines(final Writer writer, final Collection lines, final boolean flush) { writeLines(writer, lines, 0, lines.size(), flush); } public static void writeLines(final Writer writer, final Collection lines, final int offset, final int count) { writeLines(writer, lines, offset, count, false); } public static void writeLines(final Writer writer, final Collection lines, final int offset, int count, final boolean flush) { boolean isBufferedWriter = writer instanceof BufferedWriter || writer instanceof java.io.BufferedWriter; final Writer bw = isBufferedWriter ? writer : ObjectFactory.createBufferedWriter(writer); try { int lineNum = 0; for (Object line : lines) { if (lineNum++ >= offset) { if (line == null) { writer.write(N.NULL_CHAR_ARRAY); } else { writer.write(line.toString()); } writer.write(N.LINE_SEPARATOR); count--; } if (count <= 0) { break; } } if (flush || !isBufferedWriter) { bw.flush(); } } catch (IOException e) { throw new UncheckedIOException(e); } finally { if (!isBufferedWriter) { ObjectFactory.recycle((BufferedWriter) bw); } } } public static void write(final Writer writer, final boolean b) throws IOException { write(writer, b, false); } public static void write(final Writer writer, final boolean b, final boolean flush) throws IOException { writer.write(N.stringOf(b)); if (flush) { writer.flush(); } } public static void write(final Writer writer, final char c) throws IOException { write(writer, c, false); } public static void write(final Writer writer, final char c, final boolean flush) throws IOException { writer.write(c); if (flush) { writer.flush(); } } public static void write(final Writer writer, final byte b) throws IOException { write(writer, b, false); } public static void write(final Writer writer, final byte b, final boolean flush) throws IOException { writer.write(N.stringOf(b)); if (flush) { writer.flush(); } } public static void write(final Writer writer, final short s) throws IOException { write(writer, s, false); } public static void write(final Writer writer, final short s, final boolean flush) throws IOException { writer.write(N.stringOf(s)); if (flush) { writer.flush(); } } public static void write(final Writer writer, final int i) throws IOException { write(writer, i, false); } public static void write(final Writer writer, final int i, final boolean flush) throws IOException { writer.write(N.stringOf(i)); if (flush) { writer.flush(); } } public static void write(final Writer writer, final long lng) throws IOException { write(writer, lng, false); } public static void write(final Writer writer, final long lng, final boolean flush) throws IOException { writer.write(N.stringOf(lng)); if (flush) { writer.flush(); } } public static void write(final Writer writer, final float f) throws IOException { write(writer, f, false); } public static void write(final Writer writer, final float f, final boolean flush) throws IOException { writer.write(N.stringOf(f)); if (flush) { writer.flush(); } } public static void write(final Writer writer, final double d) throws IOException { write(writer, d, false); } public static void write(final Writer writer, final double d, final boolean flush) throws IOException { writer.write(N.stringOf(d)); if (flush) { writer.flush(); } } public static void write(final File out, final CharSequence str) { write(out, str, Charsets.DEFAULT); } public static void write(final File out, final CharSequence str, Charset charset) { charset = charset == null ? Charsets.DEFAULT : charset; write(out, chars2Bytes(toCharArray(str), charset)); } public static void write(final OutputStream out, final CharSequence str) { write(out, str, false); } public static void write(final OutputStream out, final CharSequence str, final Charset charset) { write(out, str, charset, false); } public static void write(final OutputStream out, final CharSequence str, final boolean flush) { write(out, str, Charsets.DEFAULT, flush); } public static void write(final OutputStream out, final CharSequence str, Charset charset, final boolean flush) { charset = charset == null ? Charsets.DEFAULT : charset; try { out.write(chars2Bytes(toCharArray(str), charset)); if (flush) { out.flush(); } } catch (IOException e) { throw new UncheckedIOException(e); } } public static void write(final Writer out, final CharSequence str) { write(out, str, false); } public static void write(final Writer out, final CharSequence str, final boolean flush) { write(out, toCharArray(str), flush); } public static void write(final File out, final char[] chars) { write(out, chars, 0, chars.length); } public static void write(final File out, final char[] chars, final int offset, final int len) { write(out, chars, offset, len, Charsets.DEFAULT); } public static void write(final File out, final char[] chars, final int offset, final int len, final Charset charset) { write(out, chars2Bytes(chars, offset, len, charset)); } public static void write(final OutputStream out, final char[] chars) { write(out, chars, 0, chars.length); } public static void write(final OutputStream out, final char[] chars, final int offset, final int len) { write(out, chars, offset, len, Charsets.DEFAULT); } public static void write(final OutputStream out, final char[] chars, final int offset, final int len, final Charset charset) { write(out, chars, offset, len, charset, false); } public static void write(final OutputStream out, final char[] chars, final boolean flush) { write(out, chars, 0, chars.length, flush); } public static void write(final OutputStream out, final char[] chars, final int offset, final int len, final boolean flush) { write(out, chars, offset, len, Charsets.DEFAULT, flush); } public static void write(final OutputStream out, final char[] chars, final int offset, final int len, final Charset charset, final boolean flush) { write(out, chars2Bytes(chars, offset, len, charset), flush); } public static void write(final Writer out, final char[] chars) { write(out, chars, 0, chars.length); } public static void write(final Writer out, final char[] chars, final int offset, final int len) { write(out, chars, offset, len, false); } public static void write(final Writer out, final char[] chars, final boolean flush) { write(out, chars, 0, chars.length, flush); } public static void write(final Writer out, final char[] chars, final int offset, final int len, final boolean flush) { try { out.write(chars, offset, len); if (flush) { out.flush(); } } catch (IOException e) { throw new UncheckedIOException(e); } } public static void write(final File out, final byte[] bytes) { write(out, bytes, 0, bytes.length); } public static void write(final File out, final byte[] bytes, final int offset, final int len) { OutputStream os = null; try { if (!out.exists()) { out.createNewFile(); } os = new FileOutputStream(out); write(os, bytes, offset, len); os.flush(); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(os); } } public static void write(final OutputStream out, final byte[] bytes) { write(out, bytes, 0, bytes.length); } public static void write(final OutputStream out, final byte[] bytes, final int offset, final int len) { write(out, bytes, offset, len, false); } public static void write(final OutputStream out, final byte[] bytes, final boolean flush) { write(out, bytes, 0, bytes.length, flush); } public static void write(final OutputStream out, final byte[] bytes, final int offset, final int len, final boolean flush) { try { out.write(bytes, offset, len); if (flush) { out.flush(); } } catch (IOException e) { throw new UncheckedIOException(e); } } public static long write(final File output, final InputStream input) { return write(output, input, 0, Long.MAX_VALUE); } /** * * @param output * @param input * @param offset by byte * @param len by byte * @return */ public static long write(final File output, final InputStream input, final long offset, final long len) { OutputStream os = null; try { if (!output.exists()) { output.createNewFile(); } os = new FileOutputStream(output); long result = write(os, input, offset, len); os.flush(); return result; } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(os); } } public static long write(final OutputStream output, final InputStream input) { return write(output, input, false); } public static long write(final OutputStream output, final InputStream input, final long offset, final long len) { return write(output, input, offset, len, false); } public static long write(final OutputStream output, final InputStream input, final boolean flush) { return write(output, input, 0, Long.MAX_VALUE, flush); } /** * * @param output * @param input * @param offset by byte * @param len by byte * @param flush * @return */ public static long write(final OutputStream output, final InputStream input, final long offset, final long len, final boolean flush) { final byte[] buf = ObjectFactory.createByteArrayBuffer(); try { if (offset > 0) { skipFully(input, offset); } if (len == 0) { return 0; } final int bufLength = buf.length; long totalCount = 0; int count = 0; while ((totalCount < len) && (EOF != (count = read(input, buf, 0, (int) Math.min(len - totalCount, bufLength))))) { output.write(buf, 0, count); totalCount += count; } if (flush) { output.flush(); } return totalCount; } catch (IOException e) { throw new UncheckedIOException(e); } finally { ObjectFactory.recycle(buf); } } public static long write(final File output, final Reader input) { return write(output, input, Charsets.DEFAULT); } public static long write(final File output, final Reader input, final Charset charset) { return write(output, input, 0, Long.MAX_VALUE, charset); } public static long write(final File output, final Reader input, final long offset, final long len) { return write(output, input, offset, len, Charsets.DEFAULT); } /** * * @param output * @param input * @param offset by char * @param len by char * @param charset * @return */ public static long write(final File output, final Reader input, final long offset, final long len, final Charset charset) { Writer writer = null; try { writer = new OutputStreamWriter(new FileOutputStream(output), charset == null ? Charsets.DEFAULT : charset); long result = write(writer, input, offset, len); writer.flush(); return result; } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(writer); } } public static long write(final Writer output, final Reader input) { return write(output, input, false); } public static long write(final Writer output, final Reader input, final long offset, final long len) { return write(output, input, offset, len, false); } public static long write(final Writer output, final Reader input, final boolean flush) { return write(output, input, 0, Long.MAX_VALUE, flush); } /** * * @param output * @param input * @param offset by char * @param len by char * @param flush * @return */ public static long write(final Writer output, final Reader input, final long offset, final long len, final boolean flush) { final char[] buf = ObjectFactory.createCharArrayBuffer(); try { if (offset > 0) { skipFully(input, offset); } if (len == 0) { return 0; } final int bufLength = buf.length; long totalCount = 0; int count = 0; while ((totalCount < len) && (EOF != (count = read(input, buf, 0, (int) Math.min(len - totalCount, bufLength))))) { output.write(buf, 0, count); totalCount += count; } if (flush) { output.flush(); } return totalCount; } catch (IOException e) { throw new UncheckedIOException(e); } finally { ObjectFactory.recycle(buf); } } // public static OutputStream base64Wrap(OutputStream os) { // return Base64.getEncoder().wrap(os); // } // // public static InputStream base64Wrap(InputStream is) { // return Base64.getDecoder().wrap(is); // } // ============================= Java 8 only // public static OutputStream base64Wrap(OutputStream os) { // return java.util.Base64.getEncoder().wrap(os); // } // // public static InputStream base64Wrap(InputStream is) { // return java.util.Base64.getDecoder().wrap(is); // } public static long write(final File output, final File input) { return write(output, input, 0, Long.MAX_VALUE); } public static long write(final File output, final File input, final long offset, final long len) { OutputStream os = null; InputStream is = null; try { os = new FileOutputStream(output); is = new FileInputStream(input); return write(os, is, offset, len, true); } catch (IOException e) { throw new UncheckedIOException(e); } finally { closeQuietly(os); closeQuietly(is); } } public static long write(final OutputStream output, final File input) { return write(output, input, false); } public static long write(final OutputStream output, final File input, final long offset, final long len) { return write(output, input, offset, len, false); } public static long write(final OutputStream output, final File input, final boolean flush) { return write(output, input, 0, Long.MAX_VALUE, flush); } /** * * @param output * @param input * @param offset * @param offset by byte * @param len by byte * @return */ public static long write(final OutputStream output, final File input, final long offset, final long len, final boolean flush) { InputStream is = null; try { is = new FileInputStream(input); return write(output, is, offset, len, flush); } catch (IOException e) { throw new UncheckedIOException(e); } finally { closeQuietly(is); } } public static long write(final Writer output, final File input) { return write(output, input, false); } public static long write(final Writer output, final File input, final long offset, final long len) { return write(output, input, offset, len, false); } public static long write(final Writer output, final File input, final boolean flush) { return write(output, input, 0, Long.MAX_VALUE, flush); } /** * * @param output * @param input * @param offset by char * @param len by char * @param flush * @return */ public static long write(final Writer output, final File input, final long offset, final long len, final boolean flush) { Reader reader = null; try { reader = new FileReader(input); return write(output, reader, offset, len, flush); } catch (IOException e) { throw new UncheckedIOException(e); } finally { closeQuietly(reader); } } public static void append(final File out, final byte[] bytes) { append(out, bytes, 0, bytes.length); } public static void append(final File out, final byte[] bytes, final int offset, final int len) { OutputStream os = null; try { if (!out.exists()) { out.createNewFile(); } os = new FileOutputStream(out, true); write(os, bytes, offset, len); os.flush(); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(os); } } public static void append(final File out, final char[] chars) { append(out, chars, 0, chars.length); } public static void append(final File out, final char[] chars, final int offset, final int len) { append(out, chars, offset, len, Charsets.DEFAULT); } public static void append(final File out, final char[] chars, final int offset, final int len, final Charset charset) { append(out, chars2Bytes(chars, offset, len, charset)); } public static void append(File output, CharSequence str) { append(output, str, Charsets.DEFAULT); } public static void append(File output, CharSequence str, Charset charset) { final char[] chs = toCharArray(str); append(output, chs, 0, chs.length, charset); } public static long append(final File output, final InputStream input) { return append(output, input, 0, Long.MAX_VALUE); } /** * * @param output * @param input * @param offset by byte * @param len by byte * @return */ public static long append(final File output, final InputStream input, final long offset, final long len) { OutputStream os = null; try { if (!output.exists()) { output.createNewFile(); } os = new FileOutputStream(output, true); long result = write(os, input, offset, len); os.flush(); return result; } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(os); } } public static long append(final File output, final Reader input) { return append(output, input, Charsets.DEFAULT); } public static long append(final File output, final Reader input, final Charset charset) { return append(output, input, 0, Long.MAX_VALUE, charset); } public static long append(final File output, final Reader input, final long offset, final long len) { return append(output, input, offset, len, Charsets.DEFAULT); } /** * * @param output * @param input * @param offset by char * @param len by char * @param charset * @return */ public static long append(final File output, final Reader input, final long offset, final long len, final Charset charset) { Writer writer = null; try { writer = new OutputStreamWriter(new FileOutputStream(output, true), charset == null ? Charsets.DEFAULT : charset); long result = write(writer, input, offset, len); writer.flush(); return result; } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(writer); } } public static long append(final File output, final File input) { return append(output, input, 0, Long.MAX_VALUE); } public static long append(final File output, final File input, final long offset, final long len) { OutputStream os = null; InputStream is = null; try { os = new FileOutputStream(output, true); is = new FileInputStream(input); return write(os, is, offset, len, true); } catch (IOException e) { throw new UncheckedIOException(e); } finally { closeQuietly(os); closeQuietly(is); } } /** * Return the count of skipped bytes. * * @param input * @param toSkip * @return */ public static long skip(final InputStream input, final long toSkip) { if (toSkip < 0) { throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip); } else if (toSkip == 0) { return 0; } final byte[] buf = ObjectFactory.createByteArrayBuffer(); long remain = toSkip; try { while (remain > 0) { long n = read(input, buf, 0, (int) Math.min(remain, buf.length)); if (n < 0) { // EOF break; } remain -= n; } return toSkip - remain; } catch (IOException e) { throw new UncheckedIOException(e); } finally { ObjectFactory.recycle(buf); } } /** * Return the count of skipped chars. * * @param input * @param toSkip * @return */ public static long skip(final Reader input, final long toSkip) { if (toSkip < 0) { throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip); } else if (toSkip == 0) { return 0; } final char[] buf = ObjectFactory.createCharArrayBuffer(); long remain = toSkip; try { while (remain > 0) { long n = read(input, buf, 0, (int) Math.min(remain, buf.length)); if (n < 0) { // EOF break; } remain -= n; } return toSkip - remain; } catch (IOException e) { throw new UncheckedIOException(e); } finally { ObjectFactory.recycle(buf); } } /** * * @param input * @param toSkip * @throws UncheckedIOException if the remaining length of the specified input is less than the specified toSkip */ public static void skipFully(final InputStream input, final long toSkip) throws UncheckedIOException { if (toSkip < 0) { throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip); } long skipped = skip(input, toSkip); if (skipped != toSkip) { throw new UncheckedIOException("Bytes to skip: " + toSkip + " actual: " + skipped); } } /** * * @param input * @param toSkip * @throws UncheckedIOException if the remaining length of the specified input is less than the specified toSkip */ public static void skipFully(final Reader input, final long toSkip) throws UncheckedIOException { long skipped = skip(input, toSkip); if (skipped != toSkip) { throw new UncheckedIOException("Chars to skip: " + toSkip + " actual: " + skipped); } } /** * Note: copied from Google Guava under Apache License v2. * * @param file * @return */ public static MappedByteBuffer map(File file) { N.requireNonNull(file); return map(file, MapMode.READ_ONLY); } /** * Note: copied from Google Guava under Apache License v2. * * Fully maps a file in to memory as per * {@link FileChannel#map(java.nio.channels.FileChannel.MapMode, long, long)} * using the requested {@link MapMode}. * *

Files are mapped from offset 0 to its length. * *

This only works for files <= {@link Integer#MAX_VALUE} bytes. * * @param file the file to map * @param mode the mode to use when mapping {@code file} * @return a buffer reflecting {@code file} * @throws FileNotFoundException if the {@code file} does not exist * * @see FileChannel#map(MapMode, long, long) * @since 2.0 */ public static MappedByteBuffer map(File file, MapMode mode) { N.requireNonNull(file); N.requireNonNull(mode); if (!file.exists()) { throw new UncheckedIOException(file.toString() + " is not found"); } return map(file, mode, 0, file.length()); } /** * Note: copied from Google Guava under Apache License v2. * * Maps a file in to memory as per * {@link FileChannel#map(java.nio.channels.FileChannel.MapMode, long, long)} * using the requested {@link MapMode}. * *

Files are mapped from offset 0 to {@code size}. * *

If the mode is {@link MapMode#READ_WRITE} and the file does not exist, * it will be created with the requested {@code size}. Thus this method is * useful for creating memory mapped files which do not yet exist. * *

This only works for files <= {@link Integer#MAX_VALUE} bytes. * * @param file the file to map * @param mode the mode to use when mapping {@code file} * @param offset * @param len * @return a buffer reflecting {@code file} * * @see FileChannel#map(MapMode, long, long) * @since 2.0 */ public static MappedByteBuffer map(File file, MapMode mode, long offset, long len) { N.requireNonNull(file); N.requireNonNull(mode); RandomAccessFile raf = null; try { raf = new RandomAccessFile(file, mode == MapMode.READ_ONLY ? "r" : "rw"); return raf.getChannel().map(mode, offset, len); } catch (IOException e) { throw new UncheckedIOException(e); } finally { IOUtil.closeQuietly(raf); } } /** * Note: copied from Google Guava under Apache License v2. * * Returns the lexically cleaned form of the path name, usually (but * not always) equivalent to the original. The following heuristics are used: * *

    *
  • empty string becomes . *
  • . stays as . *
  • fold out ./ *
  • fold out ../ when possible *
  • collapse multiple slashes *
  • delete trailing slashes (unless the path is just "/") *
* *

These heuristics do not always match the behavior of the filesystem. In * particular, consider the path {@code a/../b}, which {@code simplifyPath} * will change to {@code b}. If {@code a} is a symlink to {@code x}, {@code * a/../b} may refer to a sibling of {@code x}, rather than the sibling of * {@code a} referred to by {@code b}. * * @since 11.0 */ public static String simplifyPath(String pathname) { if (N.isNullOrEmpty(pathname)) { return "."; } pathname = pathname.replace('\\', '/'); // split the path apart String[] components = N.split(pathname, '/', true); List path = new ArrayList<>(); // resolve ., .., and // for (String component : components) { if (component.length() == 0 || component.equals(".")) { continue; } else if (component.equals("..")) { if (path.size() > 0 && !path.get(path.size() - 1).equals("..")) { path.remove(path.size() - 1); } else { path.add(".."); } } else { path.add(component); } } // put it back together String result = N.join(path, '/'); if (pathname.charAt(0) == '/') { result = "/" + result; } while (result.startsWith("/../")) { result = result.substring(3); } if (result.equals("/..")) { result = "/"; } else if ("".equals(result)) { result = "."; } return result; } /** * Note: copied from Google Guava under Apache License v2. * * Returns the file * extension for the given file name, or the empty string if the file has * no extension. The result does not include the '{@code .}'. * * @since 11.0 */ public static String getFileExtension(String fullName) { N.requireNonNull(fullName); String fileName = new File(fullName).getName(); int dotIndex = fileName.lastIndexOf('.'); return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1); } /** * Note: copied from Google Guava under Apache License v2. * * Returns the file name without its * file extension or path. This is * similar to the {@code basename} unix command. The result does not include the '{@code .}'. * * @param file The name of the file to trim the extension from. This can be either a fully * qualified file name (including a path) or just a file name. * @return The file name without its path or extension. * @since 14.0 */ public static String getNameWithoutExtension(String file) { N.requireNonNull(file); String fileName = new File(file).getName(); int dotIndex = fileName.lastIndexOf('.'); return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex); } static java.io.BufferedReader newBufferedReader(String filePath) { return newBufferedReader(new File(filePath)); } public static java.io.BufferedReader newBufferedReader(File file) { try { return new java.io.BufferedReader(new FileReader(file)); } catch (FileNotFoundException e) { throw new UncheckedIOException(e); } } public static java.io.BufferedReader newBufferedReader(File file, Charset charset) { try { return new java.io.BufferedReader(new InputStreamReader(new FileInputStream(file), charset == null ? Charsets.DEFAULT : charset)); } catch (FileNotFoundException e) { throw new UncheckedIOException(e); } } public static java.io.BufferedReader newBufferedReader(Path path) { try { return Files.newBufferedReader(path, Charsets.DEFAULT); } catch (IOException e) { throw new UncheckedIOException(e); } } public static java.io.BufferedReader newBufferedReader(Path path, Charset charset) { try { return Files.newBufferedReader(path, charset); } catch (IOException e) { throw new UncheckedIOException(e); } } public static java.io.BufferedReader newBufferedReader(InputStream is) { return new java.io.BufferedReader(new InputStreamReader(is)); } public static java.io.BufferedReader newBufferedReader(InputStream is, Charset charset) { return new java.io.BufferedReader(new InputStreamReader(is, charset == null ? Charsets.DEFAULT : charset)); } static java.io.BufferedWriter newBufferedWriter(String filePath) { return newBufferedWriter(new File(filePath)); } public static java.io.BufferedWriter newBufferedWriter(File file) { try { return new java.io.BufferedWriter(new FileWriter(file)); } catch (IOException e) { throw new UncheckedIOException(e); } } public static java.io.BufferedWriter newBufferedWriter(File file, Charset charset) { try { return new java.io.BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset == null ? Charsets.DEFAULT : charset)); } catch (IOException e) { throw new UncheckedIOException(e); } } public static java.io.BufferedWriter newBufferedWriter(OutputStream os) { return new java.io.BufferedWriter(new OutputStreamWriter(os)); } public static java.io.BufferedWriter newBufferedWriter(OutputStream os, Charset charset) { return new java.io.BufferedWriter(new OutputStreamWriter(os, charset == null ? Charsets.DEFAULT : charset)); } public static LZ4BlockInputStream newLZ4BlockInputStream(final InputStream is) { try { return new LZ4BlockInputStream(is); } catch (IOException e) { throw new UncheckedIOException(e); } } public static LZ4BlockOutputStream newLZ4BlockOutputStream(final OutputStream os) { try { return new LZ4BlockOutputStream(os); } catch (IOException e) { throw new UncheckedIOException(e); } } /** * Creates a new input stream with the specified buffer size. */ public static LZ4BlockOutputStream newLZ4BlockOutputStream(final OutputStream os, final int blockSize) { try { return new LZ4BlockOutputStream(os, blockSize); } catch (IOException e) { throw new UncheckedIOException(e); } } public static SnappyInputStream newSnappyInputStream(final InputStream is) { try { return new SnappyInputStream(is); } catch (IOException e) { throw new UncheckedIOException(e); } } public static SnappyOutputStream newSnappyOutputStream(final OutputStream os) { try { return new SnappyOutputStream(os); } catch (IOException e) { throw new UncheckedIOException(e); } } /** * Creates a new input stream with the specified buffer size. */ public static SnappyOutputStream newSnappyOutputStream(final OutputStream os, final int bufferSize) { try { return new SnappyOutputStream(os, bufferSize); } catch (IOException e) { throw new UncheckedIOException(e); } } public static GZIPInputStream newGZIPInputStream(final InputStream is) { try { return new GZIPInputStream(is); } catch (IOException e) { throw new UncheckedIOException(e); } } /** * Creates a new input stream with the specified buffer size. */ public static GZIPInputStream newGZIPInputStream(final InputStream is, final int bufferSize) { try { return new GZIPInputStream(is, bufferSize); } catch (IOException e) { throw new UncheckedIOException(e); } } public static GZIPOutputStream newGZIPOutputStream(final OutputStream os) { try { return new GZIPOutputStream(os); } catch (IOException e) { throw new UncheckedIOException(e); } } /** * Creates a new input stream with the specified buffer size. */ public static GZIPOutputStream newGZIPOutputStream(final OutputStream os, final int bufferSize) { try { return new GZIPOutputStream(os, bufferSize); } catch (IOException e) { throw new UncheckedIOException(e); } } public static void close(final ZipFile file) { if (file != null) { try { file.close(); } catch (IOException e) { throw new UncheckedIOException(e); } } } public static void close(final InputStream is) { close((Closeable) is); } public static void close(final OutputStream os) { close((Closeable) os); } public static void close(final Reader reader) { close((Closeable) reader); } public static void close(final Writer writer) { close((Closeable) writer); } public static void close(final AutoCloseable closeable) { if (closeable != null) { try { closeable.close(); } catch (Exception e) { throw new UncheckedIOException(e); } } } @SafeVarargs public static void close(final AutoCloseable... a) { if (N.isNullOrEmpty(a)) { return; } close(Arrays.asList(a)); } public static void close(final Collection c) { if (N.isNullOrEmpty(c)) { return; } RuntimeException ex = null; for (AutoCloseable closeable : c) { try { close(closeable); } catch (RuntimeException e) { if (ex == null) { ex = e; } else { ex.addSuppressed(e); } } } if (ex != null) { throw ex; } } public static void closeQuietly(final ZipFile file) { if (file != null) { try { file.close(); } catch (Throwable e) { // ignore logger.error("Failed to close", e); } } } public static void closeQuietly(final InputStream is) { closeQuietly((Closeable) is); } public static void closeQuietly(final OutputStream os) { closeQuietly((Closeable) os); } public static void closeQuietly(final Reader reader) { closeQuietly((Closeable) reader); } public static void closeQuietly(final Writer writer) { closeQuietly((Closeable) writer); } public static void closeQuietly(final AutoCloseable closeable) { if (closeable != null) { try { closeable.close(); } catch (Throwable e) { // ignore logger.error("Failed to close", e); } } } @SafeVarargs public static void closeQuietly(final AutoCloseable... a) { if (N.isNullOrEmpty(a)) { return; } closeQuietly(Arrays.asList(a)); } public static void closeQuietly(final Collection c) { if (N.isNullOrEmpty(c)) { return; } for (AutoCloseable closeable : c) { closeQuietly(closeable); } } public static void copy(final File srcFile, final File destDir) { copy(srcFile, destDir, true); } public static void copy(final File srcFile, final File destDir, final boolean preserveFileDate) { copy(srcFile, destDir, preserveFileDate, null); } /** * Copy the specified scrFile if it's a file or its sub files/directories if it's a directory to the target destDir with the specified filter * * @param srcFile * @param destDir * @param preserveFileDate * @param filter */ public static void copy(File srcFile, File destDir, final boolean preserveFileDate, final FileFilter filter) { if (!srcFile.exists()) { throw new UncheckedIOException("The source file doesn't exist: " + srcFile.getAbsolutePath()); } if (destDir.exists()) { if (destDir.isFile()) { throw new UncheckedIOException("The destination file must be directory: " + destDir.getAbsolutePath()); } } else { if (!destDir.mkdirs()) { throw new UncheckedIOException("Failed to create destination directory: " + destDir.getAbsolutePath()); } } if (destDir.canWrite() == false) { throw new UncheckedIOException("Destination '" + destDir + "' cannot be written to"); } String destCanonicalPath = null; String srcCanonicalPath = null; try { srcFile = srcFile.getCanonicalFile(); destDir = destDir.getCanonicalFile(); destCanonicalPath = destDir.getCanonicalPath(); srcCanonicalPath = srcFile.getCanonicalPath(); } catch (IOException e) { throw new UncheckedIOException(e); } if (srcFile.isDirectory()) { if (destCanonicalPath.startsWith(srcCanonicalPath) && (destCanonicalPath.length() == srcCanonicalPath.length() || destCanonicalPath.charAt(srcCanonicalPath.length()) == '/' || destCanonicalPath.charAt(srcCanonicalPath.length()) == '\\')) { throw new UncheckedIOException( "Failed to copy due to the target directory: " + destCanonicalPath + " is in or same as the source directory: " + srcCanonicalPath); } try { doCopyDirectory(srcFile, destDir, preserveFileDate, filter); } catch (IOException e) { throw new UncheckedIOException(e); } } else { File destFile = null; try { if (destDir.getCanonicalPath().equals(srcFile.getParentFile().getCanonicalPath())) { destFile = new File(destDir, "Copy of " + srcFile.getName()); } else { destFile = new File(destDir, srcFile.getName()); } } catch (IOException e) { throw new UncheckedIOException(e); } doCopyFile(srcFile, destFile, preserveFileDate); } } /** * Internal copy directory method. * * @param srcDir * the validated source directory, must not be {@code null} * @param destDir * the validated destination directory, must not be {@code null} * @param preserveFileDate * whether to preserve the file date * @param filter * the filter to apply, null means copy all directories and files * @param exclusionList * List of files and directories to exclude from the copy, may be null * @throws IOException * if an error occurs * @since 1.1 */ private static void doCopyDirectory(final File srcDir, final File destDir, final boolean preserveFileDate, final FileFilter filter) throws IOException { if (destDir.exists()) { if (destDir.isFile()) { throw new IOException("Destination '" + destDir + "' exists but is not a directory"); } } else { if (!destDir.mkdirs()) { throw new IOException("Destination '" + destDir + "' directory cannot be created"); } } final File[] subFiles = srcDir.listFiles(); if (N.isNullOrEmpty(subFiles)) { return; } for (File subFile : subFiles) { if (subFile == null) { continue; } if (filter == null || filter.accept(srcDir, subFile)) { final File dest = new File(destDir, subFile.getName()); if (subFile.isDirectory()) { doCopyDirectory(subFile, dest, preserveFileDate, null); } else { doCopyFile(subFile, dest, preserveFileDate); } } else if (subFile.isDirectory()) { final File dest = new File(destDir, subFile.getName()); doCopyDirectory(subFile, dest, preserveFileDate, filter); } } // Do this last, as the above has probably affected directory metadata if (preserveFileDate) { destDir.setLastModified(srcDir.lastModified()); } } /** * Internal copy file method. * * @param srcFile * the validated source file, must not be {@code null} * @param destFile * the validated destination file, must not be {@code null} * @param preserveFileDate * whether to preserve the file date */ private static void doCopyFile(final File srcFile, final File destFile, final boolean preserveFileDate) { if (destFile.exists()) { throw new UncheckedIOException("The destination file already existed: " + destFile.getAbsolutePath()); } FileInputStream fis = null; FileOutputStream fos = null; FileChannel input = null; FileChannel output = null; try { fis = new FileInputStream(srcFile); fos = new FileOutputStream(destFile); input = fis.getChannel(); output = fos.getChannel(); long size = input.size(); long pos = 0; long count = 0; while (pos < size) { count = ((size - pos) > FILE_COPY_BUFFER_SIZE) ? FILE_COPY_BUFFER_SIZE : (size - pos); pos += output.transferFrom(input, pos, count); } } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(output); close(fos); close(input); close(fis); } if (srcFile.length() != destFile.length()) { deleteAllIfExists(destFile); throw new UncheckedIOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'"); } if (preserveFileDate) { destFile.setLastModified(srcFile.lastModified()); } } /** * * @param source * @param target * @param options * @return * @see Files#copy(Path, Path, CopyOption...) */ @SafeVarargs public static Path copy(Path source, Path target, CopyOption... options) { try { return Files.copy(source, target, options); } catch (IOException e) { throw new UncheckedIOException(e); } } /** * * @param in * @param target * @param options * @return * @see Files#copy(InputStream, Path, CopyOption...) */ @SafeVarargs public static long copy(InputStream in, Path target, CopyOption... options) { try { return Files.copy(in, target, options); } catch (IOException e) { throw new UncheckedIOException(e); } } /** * * @param source * @param out * @return * @see Files#copy(Path, OutputStream) */ public static long copy(Path source, OutputStream out) { try { return Files.copy(source, out); } catch (IOException e) { throw new UncheckedIOException(e); } } //----------------------------------------------------------------------- /** * Copies bytes from the URL source to a file * destination. The directories up to destination * will be created if they don't already exist. destination * will be overwritten if it already exists. *

* Warning: this method does not set a connection or read timeout and thus * might block forever. Use {@link #copyURLToFile(URL, File, int, int)} * with reasonable timeouts to prevent this. * * @param source the URL to copy bytes from, must not be {@code null} * @param destination the non-directory File to write bytes to * (possibly overwriting), must not be {@code null} * @throws UncheckedIOException if source URL cannot be opened * @throws UncheckedIOException if destination is a directory * @throws UncheckedIOException if destination cannot be written * @throws UncheckedIOException if destination needs creating but can't be * @throws UncheckedIOException if an IO error occurs during copying */ public static void copyURLToFile(final URL source, final File destination) { InputStream is = null; try { is = source.openStream(); write(destination, is); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(is); } } /** * Copies bytes from the URL source to a file * destination. The directories up to destination * will be created if they don't already exist. destination * will be overwritten if it already exists. * * @param source the URL to copy bytes from, must not be {@code null} * @param destination the non-directory File to write bytes to * (possibly overwriting), must not be {@code null} * @param connectionTimeout the number of milliseconds until this method * will timeout if no connection could be established to the source * @param readTimeout the number of milliseconds until this method will * timeout if no data could be read from the source * @throws UncheckedIOException if source URL cannot be opened * @throws UncheckedIOException if destination is a directory * @throws UncheckedIOException if destination cannot be written * @throws UncheckedIOException if destination needs creating but can't be * @throws UncheckedIOException if an IO error occurs during copying */ public static void copyURLToFile(final URL source, final File destination, final int connectionTimeout, final int readTimeout) { InputStream is = null; try { final URLConnection connection = source.openConnection(); connection.setConnectTimeout(connectionTimeout); connection.setReadTimeout(readTimeout); is = connection.getInputStream(); write(destination, is); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(is); } } public static void move(final File srcFile, final File destDir) { if (!srcFile.exists()) { throw new UncheckedIOException("The source file doesn't exist: " + srcFile.getAbsolutePath()); } if (destDir.exists()) { if (destDir.isFile()) { throw new UncheckedIOException("The destination file must be directory: " + destDir.getAbsolutePath()); } } else { if (!destDir.mkdirs()) { throw new UncheckedIOException("Failed to create destination directory: " + destDir.getAbsolutePath()); } } File destFile = new File(destDir, srcFile.getName()); if (!srcFile.renameTo(destFile)) { throw new UncheckedIOException("Failed to move file from: " + srcFile.getAbsolutePath() + " to: " + destDir.getAbsolutePath()); } } /** * * @param srcFile * @param rewName the new file name under same path. * @return true if and only if the renaming succeeded; * false otherwise */ public static boolean renameTo(final File srcFile, final String newFileName) { return srcFile.renameTo(new File(srcFile.getParent() + N.FILE_SEPARATOR + newFileName)); } /** * Delete the specified file (or directory). * * @param file * @return true if the file is deleted successfully, otherwise false if the file is null or doesn't exist, or can't be deleted. */ public static boolean deleteIfExists(final File file) { if ((file == null) || !file.exists()) { return false; } return file.delete(); } /** * Delete the specified file and all its sub files/directories if it's a directory. * * @param file * @return true if the file is deleted successfully, otherwise false if the file is null or doesn't exist, or can't be deleted. */ public static boolean deleteAllIfExists(final File file) { if ((file == null) || !file.exists()) { return false; } if (file.isDirectory()) { final File[] files = file.listFiles(); if (N.notNullOrEmpty(files)) { for (File subFile : files) { if (subFile == null) { continue; } if (subFile.isFile()) { if (subFile.delete() == false) { return false; } } else { if (deleteAllIfExists(subFile) == false) { return false; } } } } } return file.delete(); } public static boolean deleteFiles(final File dir) { return deleteFiles(dir, null); } /** * Delete the specifield dir if it's a file or its sub files/directories if it's a directory with the specified filter. * * @param dir * @param filter * @return */ public static boolean deleteFiles(final File dir, FileFilter filter) { if ((dir == null) || !dir.exists()) { return false; } if (dir.isDirectory()) { final File[] files = dir.listFiles(); if (N.isNullOrEmpty(files)) { return true; } for (File subFile : files) { if (subFile == null) { continue; } if (filter == null || filter.accept(dir, subFile)) { if (subFile.isFile()) { if (subFile.delete() == false) { return false; } } else { if (deleteAllIfExists(subFile) == false) { return false; } } } else { if (subFile.isDirectory()) { if (deleteFiles(subFile, filter) == false) { return false; } } } } } else { if (filter == null || filter.accept(dir.getParentFile(), dir)) { return dir.delete(); } } return true; } /** * * @param file * @return false if file exists or failed to create new file. */ public static boolean createIfNotExists(final File file) { try { return file.exists() ? false : file.createNewFile(); } catch (IOException e) { throw new UncheckedIOException(e); } } public static void zip(final File sourceFile, final File targetFile) { ZipOutputStream zos = null; try { zos = new ZipOutputStream(new FileOutputStream(targetFile)); zipFile(sourceFile, zos, targetFile); } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(zos); } } public static void zip(final Collection sourceFiles, final File targetFile) { ZipOutputStream zos = null; try { zos = new ZipOutputStream(new FileOutputStream(targetFile)); for (File sourceFile : sourceFiles) { zipFile(sourceFile, zos, targetFile); } } catch (IOException e) { throw new UncheckedIOException(e); } finally { close(zos); } } private static void zipFile(final File sourceFile, final ZipOutputStream zos, final File targetFile) throws IOException, FileNotFoundException { if (sourceFile.isFile()) { zipFile(sourceFile, null, zos, targetFile); } else { List subFileList = listFiles(sourceFile, true, true); // subFileList.add(sourceFile); for (File subFile : subFileList) { zipFile(subFile, sourceFile, zos, targetFile); } } } private static void zipFile(final File file, final File sourceDir, final ZipOutputStream zos, final File targetFile) throws IOException, FileNotFoundException { if (file.equals(targetFile)) { return; } ZipEntry ze = null; String relativeFileName = null; if (sourceDir == null) { relativeFileName = file.getName(); } else { relativeFileName = getRelativePath(sourceDir, file); } ze = new ZipEntry(relativeFileName); ze.setSize(file.length()); ze.setTime(file.lastModified()); zos.putNextEntry(ze); InputStream is = new FileInputStream(file); final byte[] buf = ObjectFactory.createByteArrayBuffer(); try { int count = 0; while (EOF != (count = read(is, buf, 0, buf.length))) { zos.write(buf, 0, count); } } finally { ObjectFactory.recycle(buf); closeQuietly(is); } } public static void unzip(final File srcZipFile, final File targetDir) { ZipFile zip = null; ZipEntry ze = null; OutputStream os = null; InputStream is = null; final byte[] buf = ObjectFactory.createByteArrayBuffer(); final int bufLength = buf.length; try { zip = new ZipFile(srcZipFile); Enumeration entryEnum = zip.entries(); while (entryEnum.hasMoreElements()) { ze = entryEnum.nextElement(); if (ze.isDirectory()) { continue; } os = new FileOutputStream(getAbsolutePath(targetDir, ze.getName())); is = zip.getInputStream(ze); int count = 0; while (EOF != (count = read(is, buf, 0, bufLength))) { os.write(buf, 0, count); } os.flush(); closeQuietly(is); is = null; close(os); os = null; } } catch (IOException e) { throw new UncheckedIOException(e); } finally { ObjectFactory.recycle(buf); closeQuietly(zip); closeQuietly(is); close(os); } } public static void split(final File file, final int countOfParts) { split(file, countOfParts, file.getParentFile()); } public static void split(final File file, final int countOfParts, final File destDir) { final long sizeOfPart = (file.length() % countOfParts) == 0 ? (file.length() / countOfParts) : (file.length() / countOfParts) + 1; splitBySize(file, sizeOfPart, destDir); } public static void splitBySize(final File file, final long sizeOfPart) { splitBySize(file, sizeOfPart, file.getParentFile()); } /** * Mostly it's designed for (zipped/unzipped/log) text files. * * @param file * @param sizeOfPart * @param destDir */ public static void splitBySize(final File file, final long sizeOfPart, final File destDir) { final int numOfParts = (int) ((file.length() % sizeOfPart) == 0 ? (file.length() / sizeOfPart) : (file.length() / sizeOfPart) + 1); final String fileName = file.getName(); final long fileLength = file.length(); int fileSerNum = 1; final byte[] buf = ObjectFactory.createByteArrayBuffer(); InputStream input = null; OutputStream output = null; try { input = new FileInputStream(file); for (int i = 0; i < numOfParts; i++) { String subFileNmae = destDir.getAbsolutePath() + N.FILE_SEPARATOR + fileName + "_" + N.padStart(N.stringOf(fileSerNum++), 4, '0'); output = new FileOutputStream(new File(subFileNmae)); long partLength = sizeOfPart; if (i == numOfParts - 1) { partLength += fileLength % numOfParts; } int count = 0; try { while (partLength > 0 && EOF != (count = read(input, buf, 0, (int) Math.min(buf.length, partLength)))) { output.write(buf, 0, count); partLength = partLength - count; } output.flush(); } finally { close(output); } } } catch (IOException e) { throw new UncheckedIOException(e); } finally { ObjectFactory.recycle(buf); closeQuietly(input); } } static void splitByLine(final File file, final int numOfParts) { splitByLine(file, numOfParts, file.getParentFile()); } /** * Mostly it's designed for (zipped/unzipped/log) text files. * * @param file * @param numOfParts * @param destDir */ static void splitByLine(final File file, final int numOfParts, final File destDir) { final long lineNumOfPart = estimateLineCount(file, 10000) / numOfParts; int index = file.getName().lastIndexOf('.'); String prefix = file.getName().substring(0, index); String postfix = (index > 0) ? file.getName().substring(index) : ""; final Holder outputZipFile = new Holder<>(); InputStream is = null; BufferedReader br = null; BufferedWriter bw = null; int fileSerNum = 1; try { is = openFile(outputZipFile, file); br = ObjectFactory.createBufferedReader(is); String subFileNmae = destDir.getAbsolutePath() + N.FILE_SEPARATOR + prefix + "_" + N.padStart(N.stringOf(fileSerNum++), 4, '0') + postfix; bw = ObjectFactory.createBufferedWriter(new FileWriter(new File(subFileNmae))); int lineCounter = 0; String line = null; while ((line = br.readLine()) != null) { bw.write(line); bw.write(N.LINE_SEPARATOR); lineCounter++; if ((lineCounter % lineNumOfPart) == 0) { if (bw != null) { close(bw); ObjectFactory.recycle(bw); bw = null; } subFileNmae = destDir.getAbsolutePath() + N.FILE_SEPARATOR + prefix + "_" + N.padStart(N.stringOf(fileSerNum++), 4, '0') + postfix; bw = ObjectFactory.createBufferedWriter(new FileWriter(new File(subFileNmae))); } } if (bw != null) { close(bw); ObjectFactory.recycle(bw); bw = null; } } catch (IOException e) { throw new UncheckedIOException(e); } finally { if (bw != null) { close(bw); ObjectFactory.recycle(bw); } closeQuietly(is); close(outputZipFile.value()); ObjectFactory.recycle(br); } } /** * Estimate the total line count of the file by reading the specified line count ahead. * * @param file * @param byReadingLineNum * @return */ private static long estimateLineCount(final File file, final int byReadingLineNum) { final Holder outputZipFile = new Holder<>(); InputStream is = null; BufferedReader br = null; try { is = openFile(outputZipFile, file); br = ObjectFactory.createBufferedReader(is); int cnt = 0; String line = null; long bytes = 0; while (cnt < byReadingLineNum && (line = br.readLine()) != null) { bytes += line.getBytes().length; cnt++; } return cnt == 0 ? 0 : (file.length() / (bytes / cnt == 0 ? 1 : bytes / cnt)); } catch (IOException e) { throw new UncheckedIOException(e); } finally { closeQuietly(is); closeQuietly(outputZipFile.value()); ObjectFactory.recycle(br); } } public static long merge(final File[] sourceFiles, final File destFile) { return merge(N.asList(sourceFiles), destFile); } /** * Merge the specified source files into the destination file. * * @param sourceFiles * @param destFile * @return the total bytes have been merged into the destination file. */ public static long merge(final Collection sourceFiles, final File destFile) { final byte[] buf = ObjectFactory.createByteArrayBuffer(); long totalCount = 0; OutputStream output = null; try { output = new FileOutputStream(destFile); InputStream input = null; for (File file : sourceFiles) { try { input = new FileInputStream(file); int count = 0; while (EOF != (count = read(input, buf, 0, buf.length))) { output.write(buf, 0, count); totalCount += count; } } finally { close(input); } } output.flush(); } catch (IOException e) { throw new UncheckedIOException(e); } finally { ObjectFactory.recycle(buf); close(output); } return totalCount; } private static String getAbsolutePath(final File parentDir, String relativeFilePath) throws IOException { String newRelativePath = ""; for (int i = 0; i < relativeFilePath.length(); i++) { char c = relativeFilePath.charAt(i); if ((c == '\\') || (c == '/')) { newRelativePath += File.separator; } else { newRelativePath += c; } } relativeFilePath = newRelativePath; String path = parentDir.getAbsolutePath() + File.separator + relativeFilePath; File dir = new File(path.substring(0, path.lastIndexOf(File.separator))); if (!dir.exists()) { dir.mkdirs(); } return path; } private static String getRelativePath(final File parentDir, final File file) { if (file.equals(parentDir)) { return file.getName(); } else { return file.getAbsolutePath().substring(parentDir.getAbsolutePath().length() + 1); } } public static List list(final File path) { return list(path, false, false); } public static List list(File path, final boolean recursively, final boolean excludeDirectory) { List files = new ArrayList<>(); if (!path.exists()) { return files; } path = new File(path.getAbsolutePath().replace(".\\", "\\").replace("./", "/")); File[] subFiles = path.listFiles(); if (N.isNullOrEmpty(subFiles)) { return files; } for (File file : subFiles) { if (file.isFile()) { files.add(file.getAbsolutePath()); } else { if (!excludeDirectory) { files.add(file.getAbsolutePath()); } if (recursively) { files.addAll(list(file, recursively, excludeDirectory)); } } } return files; } public static List list(File path, final boolean recursively, final FileFilter filter) { List files = new ArrayList<>(); if (!path.exists()) { return files; } path = new File(path.getAbsolutePath().replace(".\\", "\\").replace("./", "/")); File[] subFiles = path.listFiles(); if (N.isNullOrEmpty(subFiles)) { return files; } for (File file : subFiles) { if (filter.accept(path, file)) { files.add(file.getAbsolutePath()); } if (recursively && file.isDirectory()) { files.addAll(list(file, recursively, filter)); } } return files; } public static List listFiles(final File path) { return listFiles(path, false, false); } public static List listFiles(final File path, final boolean recursively, final boolean excludeDirectory) { List files = new ArrayList<>(); if (!path.exists()) { return files; } File[] subFiles = path.listFiles(); if (N.isNullOrEmpty(subFiles)) { return files; } for (File file : subFiles) { if (file.isFile()) { files.add(file); } else { if (!excludeDirectory) { files.add(file); } if (recursively) { files.addAll(listFiles(file, recursively, excludeDirectory)); } } } return files; } public static List listFiles(final File path, final boolean recursively, final FileFilter filter) { List files = new ArrayList<>(); if (!path.exists()) { return files; } File[] subFiles = path.listFiles(); if (N.isNullOrEmpty(subFiles)) { return files; } for (File file : subFiles) { if (filter.accept(path, file)) { files.add(file); } if (recursively && file.isDirectory()) { files.addAll(listFiles(file, recursively, filter)); } } return files; } public static List listDirectories(final File path) { return listDirectories(path, false); } public static List listDirectories(final File path, final boolean recursively) { List files = new ArrayList<>(); if (!path.exists()) { return files; } File[] subFiles = path.listFiles(); if (N.isNullOrEmpty(subFiles)) { return files; } for (File file : subFiles) { if (file.isDirectory()) { files.add(file); if (recursively) { files.addAll(listDirectories(file, recursively)); } } } return files; } public static List listDirectories(final File path, final boolean recursively, final FileFilter filter) { List files = new ArrayList<>(); if (!path.exists()) { return files; } File[] subFiles = path.listFiles(); if (N.isNullOrEmpty(subFiles)) { return files; } for (File file : subFiles) { if (file.isDirectory()) { if (filter.accept(path, file)) { files.add(file); } if (recursively) { files.addAll(listDirectories(file, recursively, filter)); } } } return files; } //----------------------------------------------------------------------- /** * Convert from a URL to a File. *

* From version 1.1 this method will decode the URL. * Syntax such as file:///my%20docs/file.txt will be * correctly decoded to /my docs/file.txt. Starting with version * 1.5, this method uses UTF-8 to decode percent-encoded octets to characters. * Additionally, malformed percent-encoded octets are handled leniently by * passing them through literally. * * @param url the file URL to convert, {@code null} returns {@code null} * @return the equivalent File object if the URL's protocol is not file * @throws NullPointerException if the parameter is null */ public static File toFile(final URL url) { if (url.getProtocol().equals("file") == false) { throw new IllegalArgumentException("URL could not be converted to a File: " + url); } return new File(decodeUrl(url.getFile().replace('/', File.separatorChar))); } /** * Decodes the specified URL as per RFC 3986, i.e. transforms * percent-encoded octets to characters by decoding with the UTF-8 character * set. This function is primarily intended for usage with * {@link java.net.URL} which unfortunately does not enforce proper URLs. As * such, this method will leniently accept invalid characters or malformed * percent-encoded octets and simply pass them literally through to the * result string. Except for rare edge cases, this will make unencoded URLs * pass through unaltered. * * @param url The URL to decode, may be {@code null}. * @return The decoded URL or {@code null} if the input was * {@code null}. */ // unavoidable until Java 7 private static String decodeUrl(final String url) { String decoded = url; if (url != null && url.indexOf('%') >= 0) { final int n = url.length(); final StringBuffer buffer = new StringBuffer(); final ByteBuffer bytes = ByteBuffer.allocate(n); for (int i = 0; i < n;) { if (url.charAt(i) == '%') { try { do { final byte octet = (byte) Integer.parseInt(url.substring(i + 1, i + 3), 16); bytes.put(octet); i += 3; } while (i < n && url.charAt(i) == '%'); continue; } catch (final RuntimeException e) { // malformed percent-encoded octet, fall through and // append characters literally } finally { if (bytes.position() > 0) { bytes.flip(); buffer.append(Charsets.UTF_8.decode(bytes).toString()); bytes.clear(); } } } buffer.append(url.charAt(i++)); } decoded = buffer.toString(); } return decoded; } /** * Converts each of an array of URL to a File. *

* Returns an array of the same size as the input. * If the input is {@code null}, an empty array is returned. * If the input contains {@code null}, the output array contains {@code null} at the same * index. *

* This method will decode the URL. * Syntax such as file:///my%20docs/file.txt will be * correctly decoded to /my docs/file.txt. * * @param urls the file URLs to convert, {@code null} returns empty array * @return a non-{@code null} array of Files matching the input, with a {@code null} item * if there was a {@code null} at that index in the input array * @throws IllegalArgumentException if any file is not a URL file * @throws IllegalArgumentException if any file is incorrectly encoded * @since 1.1 */ public static File[] toFiles(final URL[] urls) { if (N.isNullOrEmpty(urls)) { return new File[0]; } final File[] files = new File[urls.length]; for (int i = 0; i < urls.length; i++) { files[i] = toFile(urls[i]); } return files; } public static List toFiles(final Collection urls) { if (N.isNullOrEmpty(urls)) { return new ArrayList<>(); } final List files = new ArrayList<>(urls.size()); for (URL url : urls) { files.add(toFile(url)); } return files; } public static URL toURL(final File file) { try { return file.toURI().toURL(); } catch (IOException e) { throw new UncheckedIOException(e); } } public static URL[] toURLs(final File[] files) { if (N.isNullOrEmpty(files)) { return new URL[0]; } final URL[] urls = new URL[files.length]; try { for (int i = 0; i < urls.length; i++) { urls[i] = files[i].toURI().toURL(); } } catch (IOException e) { throw new UncheckedIOException(e); } return urls; } public static List toURLs(final Collection files) { if (N.isNullOrEmpty(files)) { return new ArrayList<>(); } final List urls = new ArrayList<>(files.size()); try { for (File file : files) { urls.add(file.toURI().toURL()); } } catch (IOException e) { throw new UncheckedIOException(e); } return urls; } /** * Update the last modified time of the file to system current time if the specified file exists. * * @param file the File to touch * @return true if the file exists and last modified time is updated successfully. */ public static boolean touch(final File file) { return file.exists() && file.setLastModified(System.currentTimeMillis()); } /** * Parse the specified file/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param file parse all the sub files recursively if it's a directory. * @param lineParser always remember to handle the ending element null */ public static void parse(final File file, final Consumer lineParser) { parse(file, 0, Long.MAX_VALUE, lineParser); } /** * Parse the specified file/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param file parse all the sub files recursively if it's a directory. * @param processThreadNumber thread number used to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param lineParser always remember to handle the ending element null */ @Deprecated static void parse(final File file, final int processThreadNumber, final int queueSize, final Consumer lineParser) { parse(file, 0, Long.MAX_VALUE, processThreadNumber, queueSize, lineParser); } /** * Parse the specified file/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param file parse all the sub files recursively if it's a directory. * @param lineOffset * @param count * @param lineParser always remember to handle the ending element null */ public static void parse(final File file, final long lineOffset, final long count, final Consumer lineParser) { parse(file, lineOffset, count, 0, 0, lineParser); } /** * Parse the specified file/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param file parse all the sub files recursively if it's a directory. * @param lineOffset * @param count * @param processThreadNumber thread number used to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param lineParser always remember to handle the ending element null */ public static void parse(final File file, final long lineOffset, final long count, final int processThreadNumber, final int queueSize, final Consumer lineParser) { parse(file.isDirectory() ? listFiles(file, true, true) : N.asList(file), lineOffset, count, processThreadNumber, queueSize, lineParser); } /** * Parse the specified files/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param files parse all the sub files recursively if the element is a directory. * @param lineParser always remember to handle the ending element null */ public static void parse(final List files, final Consumer lineParser) { parse(files, 0, Long.MAX_VALUE, lineParser); } /** * Parse the specified files/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param files parse all the sub files recursively if the element is a directory. * @param processThreadNumber thread number used to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param lineParser always remember to handle the ending element null */ @Deprecated static void parse(final List files, final int processThreadNumber, final int queueSize, final Consumer lineParser) { parse(files, 0, Long.MAX_VALUE, processThreadNumber, queueSize, lineParser); } /** * Parse the specified files/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param files parse all the sub files recursively if the element is a directory. * @param lineOffset * @param count * @param lineParser always remember to handle the ending element null */ public static void parse(final List files, final long lineOffset, final long count, final Consumer lineParser) { parse(files, lineOffset, count, 0, 0, lineParser); } /** * Parse the specified files/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param files parse all the sub files recursively if the element is a directory. * @param lineOffset * @param count * @param processThreadNumber thread number used to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param lineParser always remember to handle the ending element null */ public static void parse(final List files, final long lineOffset, final long count, final int processThreadNumber, final int queueSize, final Consumer lineParser) { if (N.isNullOrEmpty(files)) { return; } final List readers = new ArrayList<>(files.size()); try { for (final File subFile : files) { if (subFile.isFile()) { readers.add(newBufferedReader(subFile)); } else { for (final File subSubFile : listFiles(subFile, true, true)) { readers.add(newBufferedReader(subSubFile)); } } } final List> iterators = new ArrayList<>(readers.size()); for (Reader reader : readers) { iterators.add(new LineIterator(reader)); } N.parse(iterators, lineOffset, count, 1, processThreadNumber, queueSize, lineParser); } finally { for (Reader reader : readers) { closeQuietly(reader); } } } /** * Parse the specified file/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param file parse all the sub files recursively if it's a directory. * @param readThreadNumber * @param lineParser always remember to handle the ending element null */ @Deprecated static void parse(final File file, final int readThreadNumber, final Consumer lineParser) { parse(file, readThreadNumber, 0, 0, lineParser); } /** * Parse the specified file/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param file parse all the sub files recursively if it's a directory. * @param readThreadNumber * @param processThreadNumber thread number used to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param lineParser always remember to handle the ending element null */ public static void parse(final File file, final int readThreadNumber, final int processThreadNumber, final int queueSize, final Consumer lineParser) { parse(file, 0, Long.MAX_VALUE, readThreadNumber, processThreadNumber, queueSize, lineParser); } public static void parse(final File file, final long lineOffset, final long count, final int readThreadNumber, final int processThreadNumber, final int queueSize, final Consumer lineParser) { parse(file.isDirectory() ? listFiles(file, true, true) : N.asList(file), lineOffset, count, readThreadNumber, processThreadNumber, queueSize, lineParser); } /** * Parse the specified files/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param files parse all the sub files recursively if the element is a directory. * @param readThreadNumber * @param lineParser always remember to handle the ending element null */ @Deprecated static void parse(final List files, final int readThreadNumber, final Consumer lineParser) { parse(files, readThreadNumber, 0, 0, lineParser); } /** * Parse the specified files/directory line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param files parse all the sub files recursively if the element is a directory. * @param readThreadNumber * @param processThreadNumber thread number used to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param lineParser always remember to handle the ending element null */ public static void parse(final List files, final int readThreadNumber, final int processThreadNumber, final int queueSize, final Consumer lineParser) { parse(files, 0, Long.MAX_VALUE, readThreadNumber, processThreadNumber, queueSize, lineParser); } public static void parse(final List files, final long lineOffset, final long count, final int readThreadNumber, final int processThreadNumber, final int queueSize, final Consumer lineParser) { if (N.isNullOrEmpty(files)) { return; } final List readers = new ArrayList<>(files.size()); try { for (final File subFile : files) { if (subFile.isFile()) { readers.add(newBufferedReader(subFile)); } else { for (final File subSubFile : listFiles(subFile, true, true)) { readers.add(newBufferedReader(subSubFile)); } } } final List> iterators = new ArrayList<>(readers.size()); for (Reader reader : readers) { iterators.add(new LineIterator(reader)); } N.parse(iterators, lineOffset, count, readThreadNumber, processThreadNumber, queueSize, lineParser); } finally { for (Reader reader : readers) { closeQuietly(reader); } } } /** * Parse the specified InputStream line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param is * @param lineParser always remember to handle the ending element null */ public static void parse(final InputStream is, final Consumer lineParser) { parse(is, 0, Long.MAX_VALUE, lineParser); } /** * Parse the specified InputStream line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param is * @param processThreadNumber thread number used to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param lineParser always remember to handle the ending element null */ @Deprecated static void parse(final InputStream is, final int processThreadNumber, final int queueSize, final Consumer lineParser) { parse(is, 0, Long.MAX_VALUE, processThreadNumber, queueSize, lineParser); } /** * Parse the specified InputStream line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param is * @param lineOffset * @param count * @param lineParser always remember to handle the ending element null */ public static void parse(final InputStream is, final long lineOffset, final long count, final Consumer lineParser) { parse(is, lineOffset, count, 0, 0, lineParser); } /** * Parse the specified InputStream line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param is * @param lineOffset * @param count * @param processThreadNumber thread number used to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param lineParser always remember to handle the ending element null */ public static void parse(final InputStream is, final long lineOffset, final long count, final int processThreadNumber, final int queueSize, final Consumer lineParser) { final BufferedReader br = ObjectFactory.createBufferedReader(is); try { parse(br, lineOffset, count, processThreadNumber, queueSize, lineParser); } finally { ObjectFactory.recycle(br); } } /** * Parse the specified Reader line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param reader * @param lineParser always remember to handle the ending element null */ public static void parse(final Reader reader, final Consumer lineParser) { parse(reader, 0, Long.MAX_VALUE, lineParser); } /** * Parse the specified Reader line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param reader * @param processThreadNumber thread number used to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param lineParser always remember to handle the ending element null */ @Deprecated static void parse(final Reader reader, final int processThreadNumber, final int queueSize, final Consumer lineParser) { parse(reader, 0, Long.MAX_VALUE, processThreadNumber, queueSize, lineParser); } /** * Parse the specified Reader line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param reader * @param lineOffset * @param count * @param lineParser always remember to handle the ending element null */ public static void parse(final Reader reader, final long lineOffset, final long count, final Consumer lineParser) { parse(reader, lineOffset, count, 0, 0, lineParser); } /** * Parse the specified Reader line by line. * The last line will always be null to identity the ending of line reading even offset/count is specified. * * @param reader * @param lineOffset * @param count * @param processThreadNumber thread number used to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param lineParser always remember to handle the ending element null */ public static void parse(final Reader reader, final long lineOffset, final long count, final int processThreadNumber, final int queueSize, final Consumer lineParser) { N.parse(new LineIterator(reader), lineOffset, count, processThreadNumber, queueSize, lineParser); } // private static void parse(final Reader reader, final File file, final AtomicLong offset, final AtomicLong count, final int processThreadNumber, // final int queueSize, final Consumer lineParser) { // logger.info(file == null ? "### Start to parse" : "### Start to parse file: " + file); // // final BufferedReader br = reader instanceof BufferedReader ? ((BufferedReader) reader) : ObjectFactory.createBufferedReader(reader); // String line = null; // // try { // while (offset.longValue() > 0 && br.readLine() != null) { // offset.decrementAndGet(); // } // // if (processThreadNumber == 0) { // while (count.longValue() > 0) { // line = br.readLine(); // // if (line == null) { // break; // } // // lineParser.accept(line); // count.decrementAndGet(); // } // // lineParser.accept(null); // } else { // final AtomicInteger activeThreadNum = new AtomicInteger(); // final ExecutorService executorService = Executors.newFixedThreadPool(processThreadNumber); // final Queue lineQueue = new ConcurrentLinkedQueue(); // final MutableBoolean isReadDone = new MutableBoolean(false); // final Holder exceptionHandle = new Holder(); // final Holder errorMessageHandle = new Holder(); // // for (int i = 0; i < processThreadNumber; i++) { // activeThreadNum.incrementAndGet(); // // executorService.execute(new Runnable() { // @Override // public void run() { // String line = null; // try { // while (exceptionHandle.getValue() == null) { // line = lineQueue.poll(); // // if (line == null) { // if (isReadDone.booleanValue()) { // line = lineQueue.poll(); // if (line == null) { // break; // } else { // lineParser.accept(line); // } // } else { // N.sleep(1); // } // } else { // lineParser.accept(line); // } // } // } catch (Throwable e) { // if (file == null) { // errorMessageHandle.setValue("### Failed to parse at line: " + line + ". " + AbacusException.getErrorMsg(e)); // } else { // errorMessageHandle // .setValue("### Failed to parse file: " + file + " at line: " + line + ". " + AbacusException.getErrorMsg(e)); // } // // exceptionHandle.setValue(e); // } finally { // activeThreadNum.decrementAndGet(); // } // } // }); // } // // try { // while (exceptionHandle.getValue() == null && count.getAndDecrement() > 0) { // while (lineQueue.size() > queueSize) { // N.sleep(1); // } // // line = br.readLine(); // // if (line == null) { // break; // } // // lineQueue.add(line); // } // } finally { // isReadDone.setTrue(); // // while (activeThreadNum.get() > 0) { // N.sleep(10); // } // } // // if (exceptionHandle.getValue() == null) { // try { // lineParser.accept(null); // } catch (Throwable e) { // errorMessageHandle.setValue("### Failed to parse null, the end of line. " + AbacusException.getErrorMsg(e)); // exceptionHandle.setValue(e); // } // } // // if (exceptionHandle.getValue() != null) { // logger.error(errorMessageHandle.getValue()); // throw new AbacusException(errorMessageHandle.getValue(), exceptionHandle.getValue()); // } // } // } catch (IOException e) { // String msg = null; // if (file == null) { // msg = "### Failed to parse at line: " + line + ". " + AbacusException.getErrorMsg(e); // } else { // msg = "### Failed to parse file: " + file + " at line: " + line + ". " + AbacusException.getErrorMsg(e); // } // logger.error(msg); // throw new UncheckedIOException(msg, e); // } finally { // if (br != reader) { // ObjectFactory.recycle(br); // } // // logger.info(file == null ? "### ### End to parse" : "### End to parse file: " + file); // } // } private static InputStream openFile(final Holder outputZipFile, final File file) throws IOException { InputStream is = null; if (file.getName().endsWith(GZ)) { is = new GZIPInputStream(new FileInputStream(file)); } else if (file.getName().endsWith(ZIP)) { ZipFile zf = new ZipFile(file); ZipEntry ze = zf.entries().nextElement(); is = zf.getInputStream(ze); outputZipFile.setValue(zf); } else { is = new FileInputStream(file); } return is; } @SuppressWarnings("deprecation") private static char[] toCharArray(CharSequence str) { return str == null ? N.NULL_CHAR_ARRAY : N.getCharsForReadOnly(str instanceof String ? (String) str : str.toString()); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy