7

Meine Anwendung verwendet Java-Klasse RandomAccessFile zum Lesen/Schreiben von Bytes in eine Datei auf SD-Karte zufällig durch Realisierung von SeekableByteChannel Schnittstelle. Jetzt muss ich es für Android 5.0 mit neuer Lollipop API umschreiben.Wie bekomme ich einen zufälligen Zugang zu einer Datei auf SD-Karte mit Hilfe von API für Lollipop präsentiert?

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

und schreiben:

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

aus/in eine Datei in neue API lesen

Ich habe the only way gefunden.

Ich möchte eine Möglichkeit haben, Kanal in einigen zufällige Position und lesen/schreiben Bytes an dieser Position. Ist das im neuen SDK 21 möglich? Bedeutet das neue SDK das Erhalten von Kanälen:

oder ein anderer Ansatz?

Antwort

7

Es scheint die einzige Möglichkeit, einen zufälligen Lese-/Schreibzugriff auf eine Datei auf der SD-Karte für SDK 21 (Lollipop) ist wie folgt zu erhalten:

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: Eine wenig optimierte Version sieht wie folgt aus:

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