@Override public int read(byte[] bytes, int off, int len) throws IOException { if (bytes == null) { throw new NullPointerException("null destination buffer"); } if ((len | off | (off + len) | (bytes.length - (off + len))) < 0) { throw new IndexOutOfBoundsException(); } if (len == 0) { return 0; } try { synchronized (stream) { final int available = stream.bufferedInputBytesRemaining(); if (available >= len) { return stream.copyBufferedBytes(bytes, off, len); } else if (stream.getDescriptor().getChannel() instanceof SelectableChannel) { SelectableChannel ch = (SelectableChannel) stream.getDescriptor().getChannel(); synchronized (ch.blockingLock()) { boolean oldBlocking = ch.isBlocking(); try { if (!oldBlocking) { ch.configureBlocking(true); } return stream.bufferedRead(ByteBuffer.wrap(bytes, off, len), true); } finally { if (!oldBlocking) { ch.configureBlocking(oldBlocking); } } } } else { return stream.bufferedRead(ByteBuffer.wrap(bytes, off, len), true); } } } catch (BadDescriptorException ex) { throw new IOException(ex.getMessage()); } catch (EOFException ex) { return -1; } }
/** * @deprecated readall do busy loop for the IO which has NONBLOCK bit. You should implement the * logic by yourself with fread(). */ @Deprecated public synchronized ByteList readall() throws IOException, BadDescriptorException { final long fileSize = descriptor.isSeekable() && descriptor.getChannel() instanceof FileChannel ? ((FileChannel) descriptor.getChannel()).size() : 0; // // Check file size - special files in /proc have zero size and need to be // handled by the generic read path. // if (fileSize > 0) { ensureRead(); FileChannel channel = (FileChannel) descriptor.getChannel(); final long left = fileSize - channel.position() + bufferedInputBytesRemaining(); if (left <= 0) { eof = true; return null; } if (left > Integer.MAX_VALUE) { if (getRuntime() != null) { throw getRuntime().newIOError("File too large"); } else { throw new IOException("File too large"); } } ByteList result = new ByteList((int) left); ByteBuffer buf = ByteBuffer.wrap(result.getUnsafeBytes(), result.begin(), (int) left); // // Copy any buffered data (including ungetc byte) // copyBufferedBytes(buf); // // Now read unbuffered directly from the file // while (buf.hasRemaining()) { final int MAX_READ_CHUNK = 1 * 1024 * 1024; // // When reading into a heap buffer, the jvm allocates a temporary // direct ByteBuffer of the requested size. To avoid allocating // a huge direct buffer when doing ludicrous reads (e.g. 1G or more) // we split the read up into chunks of no more than 1M // ByteBuffer tmp = buf.duplicate(); if (tmp.remaining() > MAX_READ_CHUNK) { tmp.limit(tmp.position() + MAX_READ_CHUNK); } int n = channel.read(tmp); if (n <= 0) { break; } buf.position(tmp.position()); } eof = true; result.length(buf.position()); return result; } else if (descriptor.isNull()) { return new ByteList(0); } else { checkReadable(); ByteList byteList = new ByteList(); ByteList read = fread(BUFSIZE); if (read == null) { eof = true; return byteList; } while (read != null) { byteList.append(read); read = fread(BUFSIZE); } return byteList; } }