我有一个InputStream,以及相对的文件名和大小。
我需要访问/阅读InputStream中的一些随机(增加)职位。此位置存储在整数数组(命名偏移量)中。
InputStream inputStream = ...
String fileName = ...
int fileSize = (int) ...
int[] offsets = new int[]{...}; // the random (increasing) offsets array现在,给定一个InputStream,我发现只有两个可能的解决方案可以跳到文件的任意(增加)位置。
第一个方法是使用InputStream的InputStream方法(请注意,我实际上使用了BufferedInputStream,因为我需要马克()和重置()文件指针)。
//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个周期是否足以确保它始终到达正确的偏移量?)
我发现的唯一替代方法是通过RandomAccessFile和下面的函数从InputStream创建一个File.createTempFile(前缀、后缀、目录)。
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;
}拥有一个RandomAccessFile实际上是一个更好的解决方案,但性能却是指数级的(最重要的是因为我将拥有不止一个文件)。
编辑:使用byte[]缓冲器=新的bytefileSize加速(和很多) 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获得“随机”访问?
发布于 2013-10-09 16:04:28
您一开始就有一个InputStream,这有点不幸,但是在这种情况下,在文件中缓冲流是没有用的,如果您总是跳过前一步。但是,您不必计算调用skip的次数,这并不是真正的兴趣所在。
您必须检查流是否已经结束,以防止无限循环。检查默认skip实现的skip,我认为您必须一直调用skip,直到它返回0为止。这将指示已经到达流的结束。就我的口味而言,JavaDoc对此有点不清楚。
发布于 2013-10-11 08:52:19
不能,InputStream是一个流,也就是说是一个顺序的构造。你的问题在措辞上有矛盾之处。
https://stackoverflow.com/questions/19276817
复制相似问题