필자는 InputStream과 상대적인 파일 이름과 크기를 가지고 있습니다.Android : InputStream에서 임의 액세스하는 방법?
InputStream에서 임의의 (증가하는) 위치에 액세스하거나 읽어야합니다. 이 위치는 정수 배열 (offsets)에 저장됩니다.
InputStream inputStream = ...
String fileName = ...
int fileSize = (int) ...
int[] offsets = new int[]{...}; // the random (increasing) offsets array
이제 InputStream이 주어지면 파일 위치를 임의로 (증가하는) 점프로 이동할 수있는 두 가지 해결책을 찾았습니다.
첫 번째는 InputStream (나는 mark() 및 reset() 파일 포인터에 필요하기 때문에 실제로, BufferedInputStream을 사용하여 주)의 skip() 방법을 사용하는 것입니다.
//Open a BufferInputStream:
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
byte[] bytes = new byte[1];
int curFilePointer = 0;
long numBytesSkipped = 0;
long numBytesToSkip = 0;
int numBytesRead = 0;
//Check the file size:
if (fileSize < offsets[offsets.length-1]) { // the last (bigger) offset is bigger then the file size...
//Debug:
Log.d(TAG, "The file is too small!\n");
return;
}
for (int i=0, k=0; i < offsets.length; i++, k=0) { // for each offset I have to jump...
try {
//Jump to the offset [i]:
while((curFilePointer < offsets[i]) && (k < 10)) { // until the correct offset is reached (at most 10 tries)
numBytesToSkip = offsets[i] - curFilePointer;
numBytesSkipped = bufferedInputStream.skip(numBytesToSkip);
curFilePointer += numBytesSkipped; // move the file pointer forward
//Debug:
Log.d(TAG, "FP: " + curFilePointer + "\n");
k++;
}
if (curFilePointer != offsets[i]) { // it did NOT jump properly... (what's going on?!)
//Debug:
Log.d(TAG, "InputStream.skip() DID NOT JUMP PROPERLY!!!\n");
break;
}
//Read the content of the file at the offset [i]:
numBytesRead = bufferedInputStream.read(bytes, 0, bytes.length);
curFilePointer += numBytesRead; // move the file pointer forward
//Debug:
Log.d(TAG, "READ [" + curFilePointer + "]: " + bytes[0] + "\n");
}
catch (IOException e) {
e.printStackTrace();
break;
}
catch (IndexOutOfBoundsException e) {
e.printStackTrace();
break;
}
}
//Close the BufferInputStream:
bufferedInputStream.close()
문제는 내 테스트 중 일부 (보통 큰) 오프셋, 그것은 정확한 바이트 수를 건너 뛰는 전에 5 번 이상을 순환하고있다,는 것이다. 정상입니까? 그리고 무엇보다도, 나는 밀어 넣을 수 있습니까? 건너 뛰기()? (즉 : 충분히 10 사이클이 좌표가 항상 올바른에 도착해야하는?)
이내가 찾은 유일한 다른 방법이 File.createTempFile(prefix, suffix, directory)과를 통해 의 InputStream에서 RandomAccessFile을 만드는 중 하나입니다 다음 기능. RandomAccessFile에를 갖는
는public static RandomAccessFile toRandomAccessFile(InputStream inputStream, File tempFile, int fileSize) throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile(tempFile, "rw");
byte[] buffer = new byte[fileSize];
int numBytesRead = 0;
while ((numBytesRead = inputStream.read(buffer)) != -1) {
randomAccessFile.write(buffer, 0, numBytesRead);
}
randomAccessFile.seek(0);
return randomAccessFile;
}
실제로 훨씬 더 나은 솔루션,하지만 (나는 하나의 파일보다 더 많이 가지고 있기 때문에 모든 이상) 성능이 기하 급수적으로 더 나쁘다.
EDIT :가 RandomAccessFile의 생성을 바이트 [완충액 = 새로운 바이트 [이는 파일 크기] 속도를 사용하여 (및 많은)! 이제
//Create a temporary RandomAccessFile:
File tempFile = File.createTempFile(fileName, null, context.getCacheDir());
RandomAccessFile randomAccessFile = toRandomAccessFile(inputStream, tempFile, fileSize);
byte[] bytes = new byte[1];
int numBytesRead = 0;
//Check the file size:
if (fileSize < offsets[offsets.length-1]) { // the last (bigger) offset is bigger then the file size...
//Debug:
Log.d(TAG, "The file is too small!\n");
return;
}
for (int i=0, k=0; i < offsets.length; i++, k=0) { // for each offset I have to jump...
try {
//Jump to the offset [i]:
randomAccessFile.seek(offsets[i]);
//Read the content of the file at the offset [i]:
numBytesRead = randomAccessFile.read(bytes, 0, bytes.length);
//Debug:
Log.d(TAG, "READ [" + (randomAccessFile.getFilePointer()-4) + "]: " + bytes[0] + "\n");
}
catch (IOException e) {
e.printStackTrace();
break;
}
catch (IndexOutOfBoundsException e) {
e.printStackTrace();
break;
}
}
//Delete the temporary RandomAccessFile:
randomAccessFile.close();
tempFile.delete();
, InputStream로부터 「랜덤 "액세스 할 수있는 더 나은 (또는 더 우아한) 솔루션은 무엇입니까?
오라클 설명서에 따르면 skip() 메소드를 신뢰해야하는지 아닌지에 대한 나의 첫 번째 질문과 관련하여 "skip 메소드는 여러 가지 이유로 작은 바이트 수를 건너 뛸 수 있습니다. 0 일 가능성이 있습니다.이는 여러 가지 조건 중 하나로 인해 발생할 수 있습니다. n 바이트를 건너 뛰기 전에 파일 끝으로 도달하는 것은 하나의 가능성에 불과합니다. " 링크 : http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#skip%28long%29 ? ZipFile.getInputStream() –
파일 (이것은 I/O 액세스를 줄일 것입니다 ...) – pskink
으로부터의 InputStream을받을 수 있나요 –