首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >安卓:如何从InputStream中随机访问?

安卓:如何从InputStream中随机访问?
EN

Stack Overflow用户
提问于 2013-10-09 15:52:57
回答 2查看 5.1K关注 0票数 1

我有一个InputStream,以及相对的文件名和大小。

我需要访问/阅读InputStream中的一些随机(增加)职位。此位置存储在整数数组(命名偏移量)中。

代码语言:javascript
复制
InputStream inputStream = ...

String fileName = ...
int fileSize = (int) ...

int[] offsets = new int[]{...};  // the random (increasing) offsets array

现在,给定一个InputStream,我发现只有两个可能的解决方案可以跳到文件的任意(增加)位置。

第一个方法是使用InputStreamInputStream方法(请注意,我实际上使用了BufferedInputStream,因为我需要马克()重置()文件指针)。

代码语言:javascript
复制
//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(前缀、后缀、目录)

代码语言:javascript
复制
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的创建!

代码语言:javascript
复制
//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获得“随机”访问?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-09 16:04:28

您一开始就有一个InputStream,这有点不幸,但是在这种情况下,在文件中缓冲流是没有用的,如果您总是跳过前一步。但是,您不必计算调用skip的次数,这并不是真正的兴趣所在。

您必须检查流是否已经结束,以防止无限循环。检查默认skip实现的skip,我认为您必须一直调用skip,直到它返回0为止。这将指示已经到达流的结束。就我的口味而言,JavaDoc对此有点不清楚。

票数 1
EN

Stack Overflow用户

发布于 2013-10-11 08:52:19

不能,InputStream是一个流,也就是说是一个顺序的构造。你的问题在措辞上有矛盾之处。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19276817

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档