7

Мое приложение использует Java-класс RandomAccessFile для чтения/записи байтов в файл на SD-карте случайно с помощью реализации интерфейса SeekableByteChannel. Теперь мне нужно переписать его для Android 5.0 с новым Lollipop API.Как получить произвольный доступ к файлу на SD-карте с помощью API, представленного для Lollipop?

Я нашел the only way следующим образом:

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

и написать:

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

из/в файл в новом API.

Я хотел бы иметь возможность устанавливать канал в некотором случайном положении и читать/писать байты в эту позицию. Возможно ли это сделать в новом SDK 21? Является ли новый SDK таким способом получение каналов:

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

или какой-либо другой подход?

ответ

7

Кажется, что единственный способ получить случайное чтение/доступ к файлу на SD-карте для SDK 21 (леденец) написать следующим образом:

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; 
    } 
} 

EDIT 15/03/2017: Немного оптимизированная версия выглядит как

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(); 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^