blob: e0d9b322855322ca88baa8a2ffe535d03cf5bcf4 [file] [log] [blame]
// 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 org.apache.doris.common.io;
import com.google.common.base.Strings;
import org.apache.logging.log4j.Logger;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
/**
* An utility class for I/O related functionality.
*/
public class IOUtils {
public static long copyBytes(InputStream in, OutputStream out,
int buffSize, long len) throws IOException {
byte buf[] = new byte[buffSize];
int totalRead = 0;
int toRead = 0;
int bytesRead = 0;
try {
toRead = (int) Math.min(buffSize, len - totalRead);
bytesRead = in.read(buf, 0, toRead);
totalRead += bytesRead;
while (bytesRead >= 0) {
out.write(buf, 0, bytesRead);
toRead = (int) Math.min(buffSize, len - totalRead);
if (toRead == 0) {
break;
}
bytesRead = in.read(buf, 0, toRead);
totalRead += bytesRead;
}
return totalRead;
} finally {
// TODO
}
}
/**
* Copies from one stream to another.
*
* @param in
* InputStrem to read from
* @param out
* OutputStream to write to
* @param buffSize
* the size of the buffer
* @param speed
* limit of the copy (B/s)
* @param close
* whether or not close the InputStream and OutputStream at the
* end. The streams are closed in the finally clause.
*/
public static long copyBytes(InputStream in, OutputStream out,
int buffSize, int speed, boolean close) throws IOException {
PrintStream ps = out instanceof PrintStream ? (PrintStream) out : null;
byte buf[] = new byte[buffSize];
long bytesReadTotal = 0;
long startTime = 0;
long sleepTime = 0;
long curTime = 0;
try {
if (speed > 0) {
startTime = System.currentTimeMillis();
}
int bytesRead = in.read(buf);
while (bytesRead >= 0) {
out.write(buf, 0, bytesRead);
if ((ps != null) && ps.checkError()) {
throw new IOException("Unable to write to output stream.");
}
bytesReadTotal += bytesRead;
if (speed > 0) {
curTime = System.currentTimeMillis();
sleepTime = bytesReadTotal / speed * 1000 / 1024
- (curTime - startTime);
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException ie) {
}
}
}
bytesRead = in.read(buf);
}
return bytesReadTotal;
} finally {
if (close) {
out.close();
in.close();
}
}
}
/**
* Copies from one stream to another.
*
* @param in
* InputStrem to read from
* @param out
* OutputStream to write to
* @param buffSize
* the size of the buffer
* @param close
* whether or not close the InputStream and OutputStream at the
* end. The streams are closed in the finally clause.
*/
public static long copyBytes(InputStream in, OutputStream out,
int buffSize, boolean close) throws IOException {
PrintStream ps = out instanceof PrintStream ? (PrintStream) out : null;
byte buf[] = new byte[buffSize];
long totalBytes = 0;
try {
int bytesRead = in.read(buf);
while (bytesRead >= 0) {
out.write(buf, 0, bytesRead);
totalBytes += bytesRead;
if ((ps != null) && ps.checkError()) {
throw new IOException("Unable to write to output stream.");
}
bytesRead = in.read(buf);
}
return totalBytes;
} finally {
if (close) {
out.close();
in.close();
}
}
}
/**
* Reads len bytes in a loop.
*
* @param in
* The InputStream to read from
* @param buf
* The buffer to fill
* @param off
* offset from the buffer
* @param len
* the length of bytes to read
* @throws IOException
* if it could not read requested number of bytes for any reason
* (including EOF)
*/
public static void readFully(InputStream in, byte buf[], int off, int len)
throws IOException {
int toRead = len;
int tmpOff = off;
while (toRead > 0) {
int ret = in.read(buf, tmpOff, toRead);
if (ret < 0) {
throw new IOException("Premeture EOF from inputStream");
}
toRead -= ret;
tmpOff += ret;
}
}
/**
* Similar to readFully(). Skips bytes in a loop.
*
* @param in
* The InputStream to skip bytes from
* @param len
* number of bytes to skip.
* @throws IOException
* if it could not skip requested number of bytes for any reason
* (including EOF)
*/
public static void skipFully(InputStream in, long len) throws IOException {
long tmpLen = len;
while (tmpLen > 0) {
long ret = in.skip(tmpLen);
if (ret < 0) {
throw new IOException("Premeture EOF from inputStream");
}
tmpLen -= ret;
}
}
/**
* Close the Closeable objects and <b>ignore</b> any {@link IOException} or
* null pointers. Must only be used for cleanup in exception handlers.
*
* @param log
* the log to record problems to at debug level. Can be null.
* @param closeables
* the objects to close
*/
public static void cleanup(Logger log, java.io.Closeable... closeables) {
for (java.io.Closeable c : closeables) {
if (c != null) {
try {
c.close();
} catch (IOException e) {
if (log != null && log.isDebugEnabled()) {
log.debug("Exception in closing {} {}", c, e);
}
}
}
}
}
/**
* Closes the stream ignoring {@link IOException}. Must only be called in
* cleaning up from exception handlers.
*
* @param stream
* the Stream to close
*/
public static void closeStream(java.io.Closeable stream) {
cleanup(null, stream);
}
/**
* Closes the socket ignoring {@link IOException}
*
* @param sock
* the Socket to close
*/
public static void closeSocket(Socket sock) {
// avoids try { close() } dance
if (sock != null) {
try {
sock.close();
} catch (IOException ignored) {
}
}
}
public static void writeOptionString(DataOutput output, String value) throws IOException {
boolean hasValue = !Strings.isNullOrEmpty(value);
output.writeBoolean(hasValue);
if (hasValue) {
Text.writeString(output, value);
}
}
public static String readOptionStringOrNull(DataInput input) throws IOException {
if (input.readBoolean()) {
return Text.readString(input);
}
return null;
}
}