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

org.scijava.io.handle.DataHandles Maven / Gradle / Ivy

/*
 * #%L
 * SciJava Common shared library for SciJava software.
 * %%
 * Copyright (C) 2009 - 2017 Board of Regents of the University of
 * Wisconsin-Madison, Broad Institute of MIT and Harvard, Max Planck
 * Institute of Molecular Cell Biology and Genetics, University of
 * Konstanz, and KNIME GmbH.
 * %%
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * #L%
 */

package org.scijava.io.handle;

import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.scijava.io.location.Location;
import org.scijava.task.Task;

/**
 * Utility methods for working with {@link DataHandle}s.
 *
 * @author Curtis Rueden
 * @author Gabriel Einsdorf
 */
public final class DataHandles {

	private static Method utfMethod;

	private DataHandles() {
		// Prevent instantiation of utility class.
	}

	/**
	 * Writes a string to the specified DataOutput using modified UTF-8 encoding
	 * in a machine-independent manner.
	 * 

* First, two bytes are written to out as if by the {@code writeShort} method * giving the number of bytes to follow. This value is the number of bytes * actually written out, not the length of the string. Following the length, * each character of the string is output, in sequence, using the modified * UTF-8 encoding for the character. If no exception is thrown, the counter * {@code written} is incremented by the total number of bytes written to the * output stream. This will be at least two plus the length of {@code str}, * and at most two plus thrice the length of {@code str}. *

* * @param str a string to be written. * @param out destination to write to * @return The number of bytes written out. * @throws IOException if an I/O error occurs. */ public static int writeUTF(final String str, final DataOutput out) throws IOException { // HACK: Strangely, DataOutputStream.writeUTF(String, DataOutput) // has package-private access. We work around it via reflection. try { return (Integer) utfMethod().invoke(null, str, out); } catch (final IllegalAccessException | IllegalArgumentException | InvocationTargetException exc) { throw new IllegalStateException( "Cannot invoke DataOutputStream.writeUTF(String, DataOutput)", exc); } } // -- Helper methods -- /** Gets the {@link #utfMethod} field, initializing if needed. */ private static Method utfMethod() { if (utfMethod == null) initUTFMethod(); return utfMethod; } /** Initializes the {@link #utfMethod} field. */ private static synchronized void initUTFMethod() { if (utfMethod != null) return; try { final Method m = DataOutputStream.class.getDeclaredMethod("writeUTF", String.class, DataOutput.class); m.setAccessible(true); utfMethod = m; } catch (final NoSuchMethodException | SecurityException exc) { throw new IllegalStateException( "No usable DataOutputStream.writeUTF(String, DataOutput)", exc); } } /** * Copies all bytes from the input to the output handle. Reading and writing * start at the current positions of the handles. * * @param in the input handle * @param out the output handle * @return the number of bytes copied * @throws IOException if an I/O error occurs. */ public static long copy(final DataHandle in, final DataHandle out) throws IOException { return copy(in, out, 0l, null); } /** * Copies all bytes from the input to the output handle, reporting the * progress to the provided task. Reading and writing start at the current * positions of the handles. * * @param in the input handle * @param out the output handle * @param task task to report progress to * @return the number of bytes copied * @throws IOException if an I/O error occurs. */ public static long copy(final DataHandle in, final DataHandle out, final Task task) throws IOException { return copy(in, out, 0l, task); } /** * Copies up to length bytes from the input to the output handle. * Reading and writing start at the current positions of the handles. Stops * early if there are no more bytes available from the input handle. * * @param in the input handle * @param out the output handle * @param length maximum number of bytes to copy; will copy all bytes if set * to 0 * @return the number of bytes copied * @throws IOException if an I/O error occurs. */ public static long copy(final DataHandle in, final DataHandle out, final int length) throws IOException { return copy(in, out, length, null); } /** * Copies up to length bytes from the input to the output handle, * reporting the progress to the provided task. Reading and writing start at * the current positions of the handles. Stops early if there are no more * bytes available from the input handle. * * @param in input handle * @param out the output handle * @param length maximum number of bytes to copy; will copy all bytes if set * to 0 * @param task a task object to use for reporting the status of the copy * operation. Can be null if no reporting is needed. * @return the number of bytes copied * @throws IOException if an I/O error occurs. */ public static long copy(final DataHandle in, final DataHandle out, final long length, final Task task) throws IOException { return copy(in, out, length, task, 64 * 1024); } /** * Copies up to length bytes from the input to the output handle, * reporting the progress to the provided task. Reading and writing start at * the current positions of the handles. Stops early if there are no more * bytes available from the input handle. Uses a buffer of the provided size, * instead of using the default size. * * @param in input handle * @param out the output handle * @param length maximum number of bytes to copy, will copy all bytes if set * to 0 * @param task a task object to use for reporting the status of the copy * operation. Can be null if no reporting is needed. * @return the number of bytes copied * @throws IOException if an I/O error occurs. */ public static long copy(final DataHandle in, final DataHandle out, final long length, final Task task, final int bufferSize) throws IOException { // get length of input final long inputlength; { long i = 0; try { i = in.length(); } catch (final IOException exc) { // Assume unknown length. i = 0; } inputlength = i; } if (task != null) { if (length > 0) task.setProgressMaximum(length); else if (inputlength > 0) task.setProgressMaximum(inputlength); } final byte[] buffer = new byte[bufferSize]; long totalRead = 0; while (true) { if (task != null && task.isCanceled()) break; final int r; // ensure we do not read more than required into the buffer if (length > 0 && totalRead + bufferSize > length) { int remaining = (int) (length - totalRead); r = in.read(buffer, 0, remaining); } else { r = in.read(buffer); } if (r <= 0) break; // EOF if (task != null && task.isCanceled()) break; out.write(buffer, 0, r); totalRead += r; if (task != null) { task.setProgressValue(task.getProgressValue() + r); } } return totalRead; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy