如何通过为Lollipop提供的API随机访问SD卡上的文件? [英] How to get random access to a file on SD-Card by means of API presented for Lollipop?

查看:112
本文介绍了如何通过为Lollipop提供的API随机访问SD卡上的文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序使用Java类 RandomAccessFile 来读取/写入字节通过实现

My application uses Java class RandomAccessFile to read/write bytes to a file on SD card randomly by means of realization of SeekableByteChannel interface. Now I need rewrite it for Android 5.0 with new Lollipop API.

我发现唯一的方法可以阅读:

InputStream inputStream = getContentResolver().openInputStream(uri);

然后写:

ParcelFileDescriptor pfd = getActivity().getContentResolver().openFileDescriptor(uri, "w");
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());

从/到新API中的文件.

from/to a file in new API.

我希望能够在某些随机位置设置频道并在该位置读取/写入字节.在新的SDK 21中可以做到这一点吗?新SDK是否暗示以这种方式获取渠道:

I would like to have an ability to set channel in some random position and read/write bytes to that position. Is it possible to do that in new SDK 21? Does new SDK imply this way obtaining of channels:

FieInputChannel fieInputChannel = fileInputStream.getChannel();
FieOutputChannel fieOutputChannel = fileOutputStream.getChannel();

或其他方法?

推荐答案

似乎可以对SD卡21(Lollipop)的SD卡上的文件进行随机读写访问的唯一方法如下:

It seems the only way to get a random read/write access to a file on SD card for SDK 21 (Lollipop) is as follows:

import android.content.Context;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import com.jetico.bestcrypt.FileManagerApplication;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class SecondaryCardChannel {//By analogy with the java.nio.channels.SeekableByteChannel
    private FileChannel fileChannel;
    private ParcelFileDescriptor pfd;
    private boolean isInputChannel;
    private long position;

    public SecondaryCardChannel(Uri treeUri, Context context) {
        try {
            pfd = context.getContentResolver().openFileDescriptor(treeUri, "rw");
            FileInputStream fis = new FileInputStream(pfd.getFileDescriptor());
            fileChannel = fis.getChannel();
            isInputChannel = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public int read(ByteBuffer buffer) {
        if (!isInputChannel) {
            try {
                fileChannel.close();
                FileInputStream fis = new FileInputStream(pfd.getFileDescriptor());
                fileChannel = fis.getChannel();
                isInputChannel = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            fileChannel.position(position);
            int bytesRead = fileChannel.read(buffer);
            position = fileChannel.position();
            return bytesRead;
        } catch (IOException e) {
            e.printStackTrace();
            return -1;
        }
    }

    public int write(ByteBuffer buffer) {
        if (isInputChannel) {
            try {
                fileChannel.close();
                FileOutputStream fos = new FileOutputStream(pfd.getFileDescriptor());
                fileChannel = fos.getChannel();
                isInputChannel = false;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            fileChannel.position(position);
            int bytesWrite = fileChannel.write(buffer);
            position = fileChannel.position();
            return bytesWrite;
        } catch (IOException e) {
            e.printStackTrace();
            return -1;
        }
    }

    public long position() throws IOException {
        return position;
    }

    public SecondaryCardChannel position(long newPosition) throws IOException {
        position = newPosition;
        return this;
    }

    public long size() throws IOException {
        return fileChannel.size();
    }

    public SecondaryCardChannel truncate(long size) throws IOException {
        fileChannel.truncate(size);
        return this;
    }
}

编辑15/03/2017: 一点点优化的版本看起来像

EDIT 15/03/2017: Little bit optimized version looks like

import android.content.Context;
import android.net.Uri;
import android.os.ParcelFileDescriptor;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class SecondaryCardChannel {
    private ParcelFileDescriptor pfdInput, pfdOutput;
    private FileInputStream fis;
    private FileOutputStream fos;
    private long position;

    public SecondaryCardChannel(Uri treeUri, Context context) {
        try {
            pfdInput = context.getContentResolver().openFileDescriptor(treeUri, "r");
            pfdOutput = context.getContentResolver().openFileDescriptor(treeUri, "rw");
            fis = new FileInputStream(pfdInput.getFileDescriptor());
            fos = new FileOutputStream(pfdOutput.getFileDescriptor());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public int read(ByteBuffer buffer) {
        try {
            FileChannel fch = fis.getChannel();
            fch.position(position);
            int bytesRead = fch.read(buffer);
            position = fch.position();
            return bytesRead;
        } catch (IOException e) {
            e.printStackTrace();
            return -1;
        }
    }

    public int write(ByteBuffer buffer) {
        try {
            FileChannel fch = fos.getChannel();
            fch.position(position);
            int bytesWrite = fch.write(buffer);
            position = fch.position();
            return bytesWrite;
        } catch (IOException e) {
            e.printStackTrace();
            return -1;
        }
    }

    public long position() throws IOException {
        return position;
    }

    public SecondaryCardChannel position(long newPosition) throws IOException {
        position = newPosition;
        return this;
    }

    public long size() throws IOException {
        return fis.getChannel().size();
    }

    public void force(boolean metadata) throws IOException {
        fos.getChannel().force(metadata);
        pfdOutput.getFileDescriptor().sync();
    }

    public long truncate(long size) throws Exception {
        FileChannel fch = fos.getChannel();
        try {
            fch.truncate(size);
            return fch.size();
        } catch (Exception e){ // Attention! Truncate is broken on removable SD card of Android 5.0
            e.printStackTrace();
            return -1;
        }
    }

    public void close() throws IOException {
        FileChannel fch = fos.getChannel();
        fch.close();

        fos.close();
        fis.close();
        pfdInput.close();
        pfdOutput.close();
    }
}

这篇关于如何通过为Lollipop提供的API随机访问SD卡上的文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆