Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /*
  2. * Copyright (C) 2008-2009, Google Inc.
  3. * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com>
  4. * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
  5. * and other copyright owners as documented in the project's IP log.
  6. *
  7. * This program and the accompanying materials are made available
  8. * under the terms of the Eclipse Distribution License v1.0 which
  9. * accompanies this distribution, is reproduced below, and is
  10. * available at http://www.eclipse.org/org/documents/edl-v10.php
  11. *
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or
  15. * without modification, are permitted provided that the following
  16. * conditions are met:
  17. *
  18. * - Redistributions of source code must retain the above copyright
  19. * notice, this list of conditions and the following disclaimer.
  20. *
  21. * - Redistributions in binary form must reproduce the above
  22. * copyright notice, this list of conditions and the following
  23. * disclaimer in the documentation and/or other materials provided
  24. * with the distribution.
  25. *
  26. * - Neither the name of the Eclipse Foundation, Inc. nor the
  27. * names of its contributors may be used to endorse or promote
  28. * products derived from this software without specific prior
  29. * written permission.
  30. *
  31. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  32. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  33. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  34. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  36. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  37. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  38. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  39. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  40. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  41. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  42. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  43. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. */
  45. package org.eclipse.jgit.util;
  46. import java.io.EOFException;
  47. import java.io.File;
  48. import java.io.FileInputStream;
  49. import java.io.FileNotFoundException;
  50. import java.io.IOException;
  51. import java.io.InputStream;
  52. import java.io.Reader;
  53. import java.nio.ByteBuffer;
  54. import java.nio.channels.ReadableByteChannel;
  55. import java.text.MessageFormat;
  56. import java.util.ArrayList;
  57. import java.util.List;
  58. import org.eclipse.jgit.internal.JGitText;
  59. /**
  60. * Input/Output utilities
  61. */
  62. public class IO {
  63. /**
  64. * Read an entire local file into memory as a byte array.
  65. *
  66. * @param path
  67. * location of the file to read.
  68. * @return complete contents of the requested local file.
  69. * @throws java.io.FileNotFoundException
  70. * the file does not exist.
  71. * @throws java.io.IOException
  72. * the file exists, but its contents cannot be read.
  73. */
  74. public static final byte[] readFully(final File path)
  75. throws FileNotFoundException, IOException {
  76. return IO.readFully(path, Integer.MAX_VALUE);
  77. }
  78. /**
  79. * Read at most limit bytes from the local file into memory as a byte array.
  80. *
  81. * @param path
  82. * location of the file to read.
  83. * @param limit
  84. * maximum number of bytes to read, if the file is larger than
  85. * only the first limit number of bytes are returned
  86. * @return complete contents of the requested local file. If the contents
  87. * exceeds the limit, then only the limit is returned.
  88. * @throws java.io.FileNotFoundException
  89. * the file does not exist.
  90. * @throws java.io.IOException
  91. * the file exists, but its contents cannot be read.
  92. */
  93. public static final byte[] readSome(final File path, final int limit)
  94. throws FileNotFoundException, IOException {
  95. FileInputStream in = new FileInputStream(path);
  96. try {
  97. byte[] buf = new byte[limit];
  98. int cnt = 0;
  99. for (;;) {
  100. int n = in.read(buf, cnt, buf.length - cnt);
  101. if (n <= 0)
  102. break;
  103. cnt += n;
  104. }
  105. if (cnt == buf.length)
  106. return buf;
  107. byte[] res = new byte[cnt];
  108. System.arraycopy(buf, 0, res, 0, cnt);
  109. return res;
  110. } finally {
  111. try {
  112. in.close();
  113. } catch (IOException ignored) {
  114. // do nothing
  115. }
  116. }
  117. }
  118. /**
  119. * Read an entire local file into memory as a byte array.
  120. *
  121. * @param path
  122. * location of the file to read.
  123. * @param max
  124. * maximum number of bytes to read, if the file is larger than
  125. * this limit an IOException is thrown.
  126. * @return complete contents of the requested local file.
  127. * @throws java.io.FileNotFoundException
  128. * the file does not exist.
  129. * @throws java.io.IOException
  130. * the file exists, but its contents cannot be read.
  131. */
  132. public static final byte[] readFully(final File path, final int max)
  133. throws FileNotFoundException, IOException {
  134. final FileInputStream in = new FileInputStream(path);
  135. try {
  136. long sz = Math.max(path.length(), 1);
  137. if (sz > max)
  138. throw new IOException(MessageFormat.format(
  139. JGitText.get().fileIsTooLarge, path));
  140. byte[] buf = new byte[(int) sz];
  141. int valid = 0;
  142. for (;;) {
  143. if (buf.length == valid) {
  144. if (buf.length == max) {
  145. int next = in.read();
  146. if (next < 0)
  147. break;
  148. throw new IOException(MessageFormat.format(
  149. JGitText.get().fileIsTooLarge, path));
  150. }
  151. byte[] nb = new byte[Math.min(buf.length * 2, max)];
  152. System.arraycopy(buf, 0, nb, 0, valid);
  153. buf = nb;
  154. }
  155. int n = in.read(buf, valid, buf.length - valid);
  156. if (n < 0)
  157. break;
  158. valid += n;
  159. }
  160. if (valid < buf.length) {
  161. byte[] nb = new byte[valid];
  162. System.arraycopy(buf, 0, nb, 0, valid);
  163. buf = nb;
  164. }
  165. return buf;
  166. } finally {
  167. try {
  168. in.close();
  169. } catch (IOException ignored) {
  170. // ignore any close errors, this was a read only stream
  171. }
  172. }
  173. }
  174. /**
  175. * Read an entire input stream into memory as a ByteBuffer.
  176. *
  177. * Note: The stream is read to its end and is not usable after calling this
  178. * method. The caller is responsible for closing the stream.
  179. *
  180. * @param in
  181. * input stream to be read.
  182. * @param sizeHint
  183. * a hint on the approximate number of bytes contained in the
  184. * stream, used to allocate temporary buffers more efficiently
  185. * @return complete contents of the input stream. The ByteBuffer always has
  186. * a writable backing array, with {@code position() == 0} and
  187. * {@code limit()} equal to the actual length read. Callers may rely
  188. * on obtaining the underlying array for efficient data access. If
  189. * {@code sizeHint} was too large, the array may be over-allocated,
  190. * resulting in {@code limit() < array().length}.
  191. * @throws java.io.IOException
  192. * there was an error reading from the stream.
  193. */
  194. public static ByteBuffer readWholeStream(InputStream in, int sizeHint)
  195. throws IOException {
  196. byte[] out = new byte[sizeHint];
  197. int pos = 0;
  198. while (pos < out.length) {
  199. int read = in.read(out, pos, out.length - pos);
  200. if (read < 0)
  201. return ByteBuffer.wrap(out, 0, pos);
  202. pos += read;
  203. }
  204. int last = in.read();
  205. if (last < 0)
  206. return ByteBuffer.wrap(out, 0, pos);
  207. @SuppressWarnings("resource" /* java 7 */)
  208. TemporaryBuffer.Heap tmp = new TemporaryBuffer.Heap(Integer.MAX_VALUE);
  209. tmp.write(out);
  210. tmp.write(last);
  211. tmp.copy(in);
  212. return ByteBuffer.wrap(tmp.toByteArray());
  213. }
  214. /**
  215. * Read the entire byte array into memory, or throw an exception.
  216. *
  217. * @param fd
  218. * input stream to read the data from.
  219. * @param dst
  220. * buffer that must be fully populated, [off, off+len).
  221. * @param off
  222. * position within the buffer to start writing to.
  223. * @param len
  224. * number of bytes that must be read.
  225. * @throws EOFException
  226. * the stream ended before dst was fully populated.
  227. * @throws java.io.IOException
  228. * there was an error reading from the stream.
  229. */
  230. public static void readFully(final InputStream fd, final byte[] dst,
  231. int off, int len) throws IOException {
  232. while (len > 0) {
  233. final int r = fd.read(dst, off, len);
  234. if (r <= 0)
  235. throw new EOFException(JGitText.get().shortReadOfBlock);
  236. off += r;
  237. len -= r;
  238. }
  239. }
  240. /**
  241. * Read as much of the array as possible from a channel.
  242. *
  243. * @param channel
  244. * channel to read data from.
  245. * @param dst
  246. * buffer that must be fully populated, [off, off+len).
  247. * @param off
  248. * position within the buffer to start writing to.
  249. * @param len
  250. * number of bytes that should be read.
  251. * @return number of bytes actually read.
  252. * @throws java.io.IOException
  253. * there was an error reading from the channel.
  254. */
  255. public static int read(ReadableByteChannel channel, byte[] dst, int off,
  256. int len) throws IOException {
  257. if (len == 0)
  258. return 0;
  259. int cnt = 0;
  260. while (0 < len) {
  261. int r = channel.read(ByteBuffer.wrap(dst, off, len));
  262. if (r <= 0)
  263. break;
  264. off += r;
  265. len -= r;
  266. cnt += r;
  267. }
  268. return cnt != 0 ? cnt : -1;
  269. }
  270. /**
  271. * Read the entire byte array into memory, unless input is shorter
  272. *
  273. * @param fd
  274. * input stream to read the data from.
  275. * @param dst
  276. * buffer that must be fully populated, [off, off+len).
  277. * @param off
  278. * position within the buffer to start writing to.
  279. * @return number of bytes in buffer or stream, whichever is shortest
  280. * @throws java.io.IOException
  281. * there was an error reading from the stream.
  282. */
  283. public static int readFully(InputStream fd, byte[] dst, int off)
  284. throws IOException {
  285. int r;
  286. int len = 0;
  287. while ((r = fd.read(dst, off, dst.length - off)) >= 0
  288. && len < dst.length) {
  289. off += r;
  290. len += r;
  291. }
  292. return len;
  293. }
  294. /**
  295. * Skip an entire region of an input stream.
  296. * <p>
  297. * The input stream's position is moved forward by the number of requested
  298. * bytes, discarding them from the input. This method does not return until
  299. * the exact number of bytes requested has been skipped.
  300. *
  301. * @param fd
  302. * the stream to skip bytes from.
  303. * @param toSkip
  304. * total number of bytes to be discarded. Must be &gt;= 0.
  305. * @throws EOFException
  306. * the stream ended before the requested number of bytes were
  307. * skipped.
  308. * @throws java.io.IOException
  309. * there was an error reading from the stream.
  310. */
  311. public static void skipFully(final InputStream fd, long toSkip)
  312. throws IOException {
  313. while (toSkip > 0) {
  314. final long r = fd.skip(toSkip);
  315. if (r <= 0)
  316. throw new EOFException(JGitText.get().shortSkipOfBlock);
  317. toSkip -= r;
  318. }
  319. }
  320. /**
  321. * Divides the given string into lines.
  322. *
  323. * @param s
  324. * the string to read
  325. * @return the string divided into lines
  326. * @since 2.0
  327. */
  328. public static List<String> readLines(final String s) {
  329. List<String> l = new ArrayList<>();
  330. StringBuilder sb = new StringBuilder();
  331. for (int i = 0; i < s.length(); i++) {
  332. char c = s.charAt(i);
  333. if (c == '\n') {
  334. l.add(sb.toString());
  335. sb.setLength(0);
  336. continue;
  337. }
  338. if (c == '\r') {
  339. if (i + 1 < s.length()) {
  340. c = s.charAt(++i);
  341. l.add(sb.toString());
  342. sb.setLength(0);
  343. if (c != '\n')
  344. sb.append(c);
  345. continue;
  346. } else { // EOF
  347. l.add(sb.toString());
  348. break;
  349. }
  350. }
  351. sb.append(c);
  352. }
  353. l.add(sb.toString());
  354. return l;
  355. }
  356. /**
  357. * Read the next line from a reader.
  358. * <p>
  359. * Like {@link java.io.BufferedReader#readLine()}, but only treats
  360. * {@code \n} as end-of-line, and includes the trailing newline.
  361. *
  362. * @param in
  363. * the reader to read from.
  364. * @param sizeHint
  365. * hint for buffer sizing; 0 or negative for default.
  366. * @return the next line from the input, always ending in {@code \n} unless
  367. * EOF was reached.
  368. * @throws java.io.IOException
  369. * there was an error reading from the stream.
  370. * @since 4.1
  371. */
  372. public static String readLine(Reader in, int sizeHint) throws IOException {
  373. if (in.markSupported()) {
  374. if (sizeHint <= 0) {
  375. sizeHint = 1024;
  376. }
  377. StringBuilder sb = new StringBuilder(sizeHint);
  378. char[] buf = new char[sizeHint];
  379. while (true) {
  380. in.mark(sizeHint);
  381. int n = in.read(buf);
  382. if (n < 0) {
  383. in.reset();
  384. return sb.toString();
  385. }
  386. for (int i = 0; i < n; i++) {
  387. if (buf[i] == '\n') {
  388. resetAndSkipFully(in, ++i);
  389. sb.append(buf, 0, i);
  390. return sb.toString();
  391. }
  392. }
  393. if (n > 0) {
  394. sb.append(buf, 0, n);
  395. }
  396. resetAndSkipFully(in, n);
  397. }
  398. } else {
  399. StringBuilder buf = sizeHint > 0
  400. ? new StringBuilder(sizeHint)
  401. : new StringBuilder();
  402. int i;
  403. while ((i = in.read()) != -1) {
  404. char c = (char) i;
  405. buf.append(c);
  406. if (c == '\n') {
  407. break;
  408. }
  409. }
  410. return buf.toString();
  411. }
  412. }
  413. private static void resetAndSkipFully(Reader fd, long toSkip) throws IOException {
  414. fd.reset();
  415. while (toSkip > 0) {
  416. long r = fd.skip(toSkip);
  417. if (r <= 0) {
  418. throw new EOFException(JGitText.get().shortSkipOfBlock);
  419. }
  420. toSkip -= r;
  421. }
  422. }
  423. private IO() {
  424. // Don't create instances of a static only utility.
  425. }
  426. }