207 lines
7.2 KiB
Java
207 lines
7.2 KiB
Java
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.frostwire.jlibtorrent;
|
|
|
|
import java.io.Closeable;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
|
|
final class Files {
|
|
|
|
private Files() {
|
|
}
|
|
|
|
private static final int EOF = -1;
|
|
|
|
/**
|
|
* Reads the contents of a file into a byte array.
|
|
* The file is always closed.
|
|
*
|
|
* @param file the file to read, must not be {@code null}
|
|
* @return the file contents, never {@code null}
|
|
* @throws IOException in case of an I/O error
|
|
* @since 1.1
|
|
*/
|
|
public static byte[] bytes(File file) throws IOException {
|
|
InputStream in = null;
|
|
try {
|
|
in = openInputStream(file);
|
|
return toByteArray(in, file.length());
|
|
} finally {
|
|
closeQuietly(in);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Opens a {@link java.io.FileInputStream} for the specified file, providing better
|
|
* error messages than simply calling <code>new FileInputStream(file)</code>.
|
|
* <p>
|
|
* At the end of the method either the stream will be successfully opened,
|
|
* or an exception will have been thrown.
|
|
* <p>
|
|
* An exception is thrown if the file does not exist.
|
|
* An exception is thrown if the file object exists but is a directory.
|
|
* An exception is thrown if the file exists but cannot be read.
|
|
*
|
|
* @param file the file to open for input, must not be {@code null}
|
|
* @return a new {@link java.io.FileInputStream} for the specified file
|
|
* @throws java.io.FileNotFoundException if the file does not exist
|
|
* @throws IOException if the file object is a directory
|
|
* @throws IOException if the file cannot be read
|
|
* @since 1.3
|
|
*/
|
|
private static FileInputStream openInputStream(File file) throws IOException {
|
|
if (file.exists()) {
|
|
if (file.isDirectory()) {
|
|
throw new IOException("File '" + file + "' exists but is a directory");
|
|
}
|
|
if (file.canRead() == false) {
|
|
throw new IOException("File '" + file + "' cannot be read");
|
|
}
|
|
} else {
|
|
throw new FileNotFoundException("File '" + file + "' does not exist");
|
|
}
|
|
return new FileInputStream(file);
|
|
}
|
|
|
|
/**
|
|
* Get contents of an <code>InputStream</code> as a <code>byte[]</code>.
|
|
* Use this method instead of <code>toByteArray(InputStream)</code>
|
|
* when <code>InputStream</code> size is known.
|
|
* <b>NOTE:</b> the method checks that the length can safely be cast to an int without truncation
|
|
* before using {@link #toByteArray(java.io.InputStream, int)} to read into the byte array.
|
|
* (Arrays can have no more than Integer.MAX_VALUE entries anyway)
|
|
*
|
|
* @param input the <code>InputStream</code> to read from
|
|
* @param size the size of <code>InputStream</code>
|
|
* @return the requested byte array
|
|
* @throws IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
|
|
* @throws IllegalArgumentException if size is less than zero or size is greater than Integer.MAX_VALUE
|
|
* @see #toByteArray(java.io.InputStream, int)
|
|
* @since 2.1
|
|
*/
|
|
private static byte[] toByteArray(InputStream input, long size) throws IOException {
|
|
|
|
if (size > Integer.MAX_VALUE) {
|
|
throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + size);
|
|
}
|
|
|
|
return toByteArray(input, (int) size);
|
|
}
|
|
|
|
/**
|
|
* Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
|
|
* Use this method instead of <code>toByteArray(InputStream)</code>
|
|
* when <code>InputStream</code> size is known
|
|
*
|
|
* @param input the <code>InputStream</code> to read from
|
|
* @param size the size of <code>InputStream</code>
|
|
* @return the requested byte array
|
|
* @throws java.io.IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
|
|
* @throws IllegalArgumentException if size is less than zero
|
|
* @since 2.1
|
|
*/
|
|
private static byte[] toByteArray(InputStream input, int size) throws IOException {
|
|
|
|
if (size < 0) {
|
|
throw new IllegalArgumentException("Size must be equal or greater than zero: " + size);
|
|
}
|
|
|
|
if (size == 0) {
|
|
return new byte[0];
|
|
}
|
|
|
|
byte[] data = new byte[size];
|
|
int offset = 0;
|
|
int readed;
|
|
|
|
while (offset < size && (readed = input.read(data, offset, size - offset)) != EOF) {
|
|
offset += readed;
|
|
}
|
|
|
|
if (offset != size) {
|
|
throw new IOException("Unexpected readed size. current: " + offset + ", excepted: " + size);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* Unconditionally close an <code>InputStream</code>.
|
|
* <p>
|
|
* Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
|
|
* This is typically used in finally blocks.
|
|
* <p>
|
|
* Example code:
|
|
* <pre>
|
|
* byte[] data = new byte[1024];
|
|
* InputStream in = null;
|
|
* try {
|
|
* in = new FileInputStream("foo.txt");
|
|
* in.read(data);
|
|
* in.close(); //close errors are handled
|
|
* } catch (Exception e) {
|
|
* // error handling
|
|
* } finally {
|
|
* IOUtils.closeQuietly(in);
|
|
* }
|
|
* </pre>
|
|
*
|
|
* @param input the InputStream to close, may be null or already closed
|
|
*/
|
|
static void closeQuietly(InputStream input) {
|
|
closeQuietly((Closeable) input);
|
|
}
|
|
|
|
/**
|
|
* Unconditionally close a <code>Closeable</code>.
|
|
* <p>
|
|
* Equivalent to {@link java.io.Closeable#close()}, except any exceptions will be ignored.
|
|
* This is typically used in finally blocks.
|
|
* <p>
|
|
* Example code:
|
|
* <pre>
|
|
* Closeable closeable = null;
|
|
* try {
|
|
* closeable = new FileReader("foo.txt");
|
|
* // process closeable
|
|
* closeable.close();
|
|
* } catch (Exception e) {
|
|
* // error handling
|
|
* } finally {
|
|
* IOUtils.closeQuietly(closeable);
|
|
* }
|
|
* </pre>
|
|
*
|
|
* @param closeable the object to close, may be null or already closed
|
|
* @since 2.0
|
|
*/
|
|
static void closeQuietly(Closeable closeable) {
|
|
try {
|
|
if (closeable != null) {
|
|
closeable.close();
|
|
}
|
|
} catch (IOException ioe) {
|
|
// ignore
|
|
}
|
|
}
|
|
}
|