|
9 | 9 | * %% |
10 | 10 | * Redistribution and use in source and binary forms, with or without |
11 | 11 | * modification, are permitted provided that the following conditions are met: |
12 | | - * |
| 12 | + * |
13 | 13 | * 1. Redistributions of source code must retain the above copyright notice, |
14 | 14 | * this list of conditions and the following disclaimer. |
15 | 15 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
16 | 16 | * this list of conditions and the following disclaimer in the documentation |
17 | 17 | * and/or other materials provided with the distribution. |
18 | | - * |
| 18 | + * |
19 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
20 | 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
38 | 38 | import java.lang.reflect.InvocationTargetException; |
39 | 39 | import java.lang.reflect.Method; |
40 | 40 |
|
| 41 | +import org.scijava.io.location.Location; |
| 42 | +import org.scijava.task.Task; |
| 43 | + |
41 | 44 | /** |
42 | 45 | * Utility methods for working with {@link DataHandle}s. |
43 | | - * |
| 46 | + * |
44 | 47 | * @author Curtis Rueden |
| 48 | + * @author Gabriel Einsdorf |
45 | 49 | */ |
46 | 50 | public final class DataHandles { |
47 | 51 |
|
@@ -108,4 +112,141 @@ private static synchronized void initUTFMethod() { |
108 | 112 | "No usable DataOutputStream.writeUTF(String, DataOutput)", exc); |
109 | 113 | } |
110 | 114 | } |
| 115 | + |
| 116 | + /** |
| 117 | + * Copies all bytes from the input to the output handle. Reading and writing |
| 118 | + * start at the current positions of the handles. |
| 119 | + * |
| 120 | + * @param in the input handle |
| 121 | + * @param out the output handle |
| 122 | + * @return the number of bytes copied |
| 123 | + * @throws IOException if an I/O error occurs. |
| 124 | + */ |
| 125 | + public static long copy(final DataHandle<Location> in, |
| 126 | + final DataHandle<Location> out) throws IOException |
| 127 | + { |
| 128 | + return copy(in, out, 0l, null); |
| 129 | + } |
| 130 | + |
| 131 | + /** |
| 132 | + * Copies all bytes from the input to the output handle, reporting the |
| 133 | + * progress to the provided task. Reading and writing start at the current |
| 134 | + * positions of the handles. |
| 135 | + * |
| 136 | + * @param in the input handle |
| 137 | + * @param out the output handle |
| 138 | + * @param task task to report progress to |
| 139 | + * @return the number of bytes copied |
| 140 | + * @throws IOException if an I/O error occurs. |
| 141 | + */ |
| 142 | + public static long copy(final DataHandle<Location> in, |
| 143 | + final DataHandle<Location> out, final Task task) throws IOException |
| 144 | + { |
| 145 | + return copy(in, out, 0l, task); |
| 146 | + } |
| 147 | + |
| 148 | + /** |
| 149 | + * Copies up to <code>length</code> bytes from the input to the output handle. |
| 150 | + * Reading and writing start at the current positions of the handles. Stops |
| 151 | + * early if there are no more bytes available from the input handle. |
| 152 | + * |
| 153 | + * @param in the input handle |
| 154 | + * @param out the output handle |
| 155 | + * @param length maximum number of bytes to copy; will copy all bytes if set |
| 156 | + * to <code>0</code> |
| 157 | + * @return the number of bytes copied |
| 158 | + * @throws IOException if an I/O error occurs. |
| 159 | + */ |
| 160 | + public static long copy(final DataHandle<Location> in, |
| 161 | + final DataHandle<Location> out, final int length) throws IOException |
| 162 | + { |
| 163 | + return copy(in, out, length, null); |
| 164 | + } |
| 165 | + |
| 166 | + /** |
| 167 | + * Copies up to <code>length</code> bytes from the input to the output handle, |
| 168 | + * reporting the progress to the provided task. Reading and writing start at |
| 169 | + * the current positions of the handles. Stops early if there are no more |
| 170 | + * bytes available from the input handle. |
| 171 | + * |
| 172 | + * @param in input handle |
| 173 | + * @param out the output handle |
| 174 | + * @param length maximum number of bytes to copy; will copy all bytes if set |
| 175 | + * to <code>0</code> |
| 176 | + * @param task a task object to use for reporting the status of the copy |
| 177 | + * operation. Can be <code>null</code> if no reporting is needed. |
| 178 | + * @return the number of bytes copied |
| 179 | + * @throws IOException if an I/O error occurs. |
| 180 | + */ |
| 181 | + public static long copy(final DataHandle<Location> in, |
| 182 | + final DataHandle<Location> out, final long length, final Task task) |
| 183 | + throws IOException |
| 184 | + { |
| 185 | + return copy(in, out, length, task, 64 * 1024); |
| 186 | + } |
| 187 | + |
| 188 | + /** |
| 189 | + * Copies up to <code>length</code> bytes from the input to the output handle, |
| 190 | + * reporting the progress to the provided task. Reading and writing start at |
| 191 | + * the current positions of the handles. Stops early if there are no more |
| 192 | + * bytes available from the input handle. Uses a buffer of the provided size, |
| 193 | + * instead of using the default size. |
| 194 | + * |
| 195 | + * @param in input handle |
| 196 | + * @param out the output handle |
| 197 | + * @param length maximum number of bytes to copy, will copy all bytes if set |
| 198 | + * to <code>0</code> |
| 199 | + * @param task a task object to use for reporting the status of the copy |
| 200 | + * operation. Can be <code>null</code> if no reporting is needed. |
| 201 | + * @return the number of bytes copied |
| 202 | + * @throws IOException if an I/O error occurs. |
| 203 | + */ |
| 204 | + public static long copy(final DataHandle<Location> in, |
| 205 | + final DataHandle<Location> out, final long length, final Task task, |
| 206 | + final int bufferSize) throws IOException |
| 207 | + { |
| 208 | + |
| 209 | + // get length of input |
| 210 | + final long inputlength; |
| 211 | + { |
| 212 | + long i = 0; |
| 213 | + try { |
| 214 | + i = in.length(); |
| 215 | + } |
| 216 | + catch (final IOException exc) { |
| 217 | + // Assume unknown length. |
| 218 | + i = 0; |
| 219 | + } |
| 220 | + inputlength = i; |
| 221 | + } |
| 222 | + |
| 223 | + if (task != null) { |
| 224 | + if (length > 0) task.setProgressMaximum(length); |
| 225 | + else if (inputlength > 0) task.setProgressMaximum(inputlength); |
| 226 | + } |
| 227 | + |
| 228 | + final byte[] buffer = new byte[bufferSize]; |
| 229 | + long totalRead = 0; |
| 230 | + |
| 231 | + while (true) { |
| 232 | + if (task != null && task.isCanceled()) break; |
| 233 | + final int r; |
| 234 | + // ensure we do not read more than required into the buffer |
| 235 | + if (length > 0 && totalRead + bufferSize > length) { |
| 236 | + int remaining = (int) (length - totalRead); |
| 237 | + r = in.read(buffer, 0, remaining); |
| 238 | + } |
| 239 | + else { |
| 240 | + r = in.read(buffer); |
| 241 | + } |
| 242 | + if (r <= 0) break; // EOF |
| 243 | + if (task != null && task.isCanceled()) break; |
| 244 | + out.write(buffer, 0, r); |
| 245 | + totalRead += r; |
| 246 | + if (task != null) { |
| 247 | + task.setProgressValue(task.getProgressValue() + r); |
| 248 | + } |
| 249 | + } |
| 250 | + return totalRead; |
| 251 | + } |
111 | 252 | } |
0 commit comments