1. Source
We need to track the Nativie Implementation of FileInputStream's Read and start to take a detour. The implementation of FileInputStream in the Java project is different from that in the Android project. In addition, the analysis in http://blog.chinaunix.net/uid-26926660-id-3326678.htmlis very good.
2. java. io. FileInputStream
[Java]
Import libcore. io. Libcore;
Import libcore. io. Streams;
@ Override public int read () throws IOException {
Return Streams. readSingleByte (this );
}
@ Override public int read (byte [] buffer, int byteOffset, int byteCount) throws IOException {
Return IoBridge. read (fd, buffer, byteOffset, byteCount );
}
Import libcore. io. Libcore;
Import libcore. io. Streams;
@ Override public int read () throws IOException {
Return Streams. readSingleByte (this );
}
@ Override public int read (byte [] buffer, int byteOffset, int byteCount) throws IOException {
Return IoBridge. read (fd, buffer, byteOffset, byteCount );
} Continue tracking Streams. readSingleByte and IoBridge. read
3. libcore. io. Streams
Http://grepcode.com/file/repo1.maven.org/maven2/com.google.okhttp/okhttp/20120626/libcore/io/Streams.java
[Java]
Public static int readSingleByte (InputStream in) throws IOException {
Byte [] buffer = new byte [1];
Int result = in. read (buffer, 0, 1 );
Return (result! =-1 )? Buffer [0] & 0xff:-1;
}
Public static int readSingleByte (InputStream in) throws IOException {
Byte [] buffer = new byte [1];
Int result = in. read (buffer, 0, 1 );
Return (result! =-1 )? Buffer [0] & 0xff:-1;
}
InputStream is used here. read (byte [], int, int), actually called FileInputStream. read (byte [], int, int), and finally call IoBridge. read (byte [], int, int)
4. libcore. io. ioBridge
Https://android.googlesource.com/platform/libcore/+/796f0d5a4e7b83c3efc5e587b6766977dc20b0c3/luni/src/main/java/libcore/io/IoBridge.java
[Java]
/**
* Java. io thinks that a read at EOF is an error and shoshould return-1, contrary to traditional
* Unix practice where you 'd read until you got 0 bytes (and any future read wowould return-1 ).
*/
Public static int read (FileDescriptor fd, byte [] bytes, int byteOffset, int byteCount) throws IOException {
Arrays. checkOffsetAndCount (bytes. length, byteOffset, byteCount );
If (byteCount = 0 ){
Return 0;
}
Try {
Int readCount = Libcore. OS. read (fd, bytes, byteOffset, byteCount );
If (readCount = 0 ){
Return-1;
}
Return readCount;
} Catch (ErrnoException errnoException ){
If (errnoException. errno = EAGAIN ){
// We return 0 rather than throw if we try to read from an empty non-blocking pipe.
Return 0;
}
Throw errnoException. rethrowAsIOException ();
}
}
/**
* Java. io thinks that a read at EOF is an error and shoshould return-1, contrary to traditional
* Unix practice where you 'd read until you got 0 bytes (and any future read wowould return-1 ).
*/
Public static int read (FileDescriptor fd, byte [] bytes, int byteOffset, int byteCount) throws IOException {
Arrays. checkOffsetAndCount (bytes. length, byteOffset, byteCount );
If (byteCount = 0 ){
Return 0;
}
Try {
Int readCount = Libcore. OS. read (fd, bytes, byteOffset, byteCount );
If (readCount = 0 ){
Return-1;
}
Return readCount;
} Catch (ErrnoException errnoException ){
If (errnoException. errno = EAGAIN ){
// We return 0 rather than throw if we try to read from an empty non-blocking pipe.
Return 0;
}
Throw errnoException. rethrowAsIOException ();
}
}
5. libcore. io. Libcore
Http://grepcode.com/file/repo1.maven.org/maven2/org.robovm/robovm-rt/0.0.2/libcore/io/Libcore.java#Libcore
[Java]
Package libcore. io;
Public final class Libcore {
Private Libcore (){}
Public static OS OS = new BlockGuardOs (new Posix ());
}
Package libcore. io;
Public final class Libcore {
Private Libcore (){}
Public static OS OS = new BlockGuardOs (new Posix ());
}
This is a bit broken. BlockGuardOs has some calls,
6. Libcore. io. Posix
Https://android.googlesource.com/platform/libcore/+/6c9b5377550a9649ed1532d1fcdfeba116c74ead/luni/src/main/java/libcore/io/Posix.java
[Java]
Public int read (FileDescriptor fd, ByteBuffer buffer) throws ErrnoException {
If (buffer. isDirect ()){
Return readBytes (fd, buffer, buffer. position (), buffer. remaining ());
} Else {
Return readBytes (fd, NioUtils. unsafeArray (buffer), NioUtils. unsafeArrayOffset (buffer) + buffer. position (), buffer. remaining ());
}
}
Public int read (FileDescriptor fd, ByteBuffer buffer) throws ErrnoException {
If (buffer. isDirect ()){
Return readBytes (fd, buffer, buffer. position (), buffer. remaining ());
} Else {
Return readBytes (fd, NioUtils. unsafeArray (buffer), NioUtils. unsafeArrayOffset (buffer) + buffer. position (), buffer. remaining ());
}
}
Here is the native method.
7. src/main/native/libcore_io_Posix.cpp
Https://android.googlesource.com/platform/libcore/+/721ceca2a52a3c27aa751476c8562e1e68088e15/luni/src/main/native/libcore_io_Posix.cpp
[Cpp]
# Include <unistd. h>
# Include "ScopeBytes. h"
Static jint Posix_readBytes (JNIEnv * env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount ){
ScopedBytesRW bytes (env, javaBytes );
If (bytes. get () = NULL ){
Return-1;
}
Int fd = jniGetFDFromFileDescriptor (env, javaFd );
Return throwIfMinusOne (env, "read", TEMP_FAILURE_RETRY (read (fd, bytes. get () + byteOffset, byteCount )));
}
# Include <unistd. h>
# Include "ScopeBytes. h"
Static jint Posix_readBytes (JNIEnv * env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount ){
ScopedBytesRW bytes (env, javaBytes );
If (bytes. get () = NULL ){
Return-1;
}
Int fd = jniGetFDFromFileDescriptor (env, javaFd );
Return throwIfMinusOne (env, "read", TEMP_FAILURE_RETRY (read (fd, bytes. get () + byteOffset, byteCount )));
}
First: return throwIfMinusOne (env, "write", TEMP_FAILURE_RETRY (write (fd, bytes. get () + byteOffset, byteCount )));
ThrowIfMinusOne and TEMP_FAILURE_RETRY are macro definitions.
Write is the C language library function in <unistd. h>.
Second: ScopedBytesRW
Https://android.googlesource.com/platform/libnativehelper/+/3d9d2148155c2e0b3bf51cd548f58f93d1199a4e/include/nativehelper/ScopedBytes.h
This file is relatively simple. It only includes JNIHelper. h to distinguish byte [] s from ByteBuffers.
[Cpp]
Class ScopedBytesRW: public ScopedBytes <false> {
Public:
ScopedBytesRW (JNIEnv * env, jobject object): ScopedBytes <false> (env, object ){}
Jbyte * get (){
Return mPtr;
}
};
Class ScopedBytesRW: public ScopedBytes <false> {
Public:
ScopedBytesRW (JNIEnv * env, jobject object): ScopedBytes <false> (env, object ){}
Jbyte * get (){
Return mPtr;
}
};