* Actually the whole impl can't be more sucks, will import algorithm to manage buffer and read strategy further
105 lines
2.9 KiB
Java
105 lines
2.9 KiB
Java
package com.hippo;
|
|
|
|
import android.content.Context;
|
|
import android.net.Uri;
|
|
import android.os.ParcelFileDescriptor;
|
|
import android.system.ErrnoException;
|
|
import android.system.Os;
|
|
import android.system.OsConstants;
|
|
|
|
import java.io.Closeable;
|
|
import java.io.FileDescriptor;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
|
|
public class UriArchiveAccessor implements Closeable {
|
|
public static int OPEN_OK = 1;
|
|
public static int OPEN_ERR = 2;
|
|
private final OsReadableFile osf;
|
|
|
|
public UriArchiveAccessor(Context ctx, Uri uri) throws FileNotFoundException {
|
|
osf = new OsReadableFile(ctx, uri);
|
|
}
|
|
|
|
public int open() {
|
|
return openArchive(osf);
|
|
}
|
|
|
|
public void extractTargetIndexToOutputStream(int index, OutputStream os) {
|
|
extracttoOutputStream(osf, index, os);
|
|
}
|
|
|
|
private native int openArchive(OsReadableFile osf);
|
|
private native int extracttoOutputStream(OsReadableFile osf, int index, OutputStream os);
|
|
|
|
@Override
|
|
public void close() throws IOException {
|
|
osf.close();
|
|
}
|
|
|
|
static class OsReadableFile {
|
|
ParcelFileDescriptor pfd;
|
|
FileDescriptor fd;
|
|
|
|
public OsReadableFile(Context ctx, Uri uri) throws FileNotFoundException {
|
|
pfd = ctx.getContentResolver().openFileDescriptor(uri, "r");
|
|
fd = pfd.getFileDescriptor();
|
|
}
|
|
|
|
public int read(byte[] b, int off, int len) throws IOException, ErrnoException {
|
|
return Os.read(fd, b, off, len);
|
|
}
|
|
|
|
public int read(byte[] b) throws IOException, ErrnoException {
|
|
return read(b, 0, b.length);
|
|
}
|
|
|
|
public long length() throws IOException, ErrnoException {
|
|
return Os.fstat(fd).st_size;
|
|
}
|
|
|
|
public long seek(long pos, int whence) throws IOException, ErrnoException {
|
|
try {
|
|
return Os.lseek(fd, pos, whence);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
return -30;
|
|
}
|
|
}
|
|
|
|
public void rewind() throws IOException, ErrnoException {
|
|
Os.lseek(fd, 0, OsConstants.SEEK_SET);
|
|
}
|
|
|
|
public long skip(long n) throws IOException, ErrnoException {
|
|
long pos;
|
|
long len;
|
|
long newpos;
|
|
|
|
if (n <= 0) {
|
|
return 0;
|
|
}
|
|
pos = Os.lseek(fd, 0L, OsConstants.SEEK_CUR);
|
|
len = length();
|
|
newpos = pos + n;
|
|
if (newpos > len) {
|
|
newpos = len;
|
|
}
|
|
seek(newpos, OsConstants.SEEK_SET);
|
|
|
|
/* return the actual number of bytes skipped */
|
|
return newpos - pos;
|
|
}
|
|
|
|
public void close() throws IOException {
|
|
pfd.close();
|
|
try {
|
|
Os.close(fd);
|
|
} catch (ErrnoException e) {
|
|
throw new IOException("An ErrnoException occurs", e);
|
|
}
|
|
}
|
|
}
|
|
}
|