对于RandomAccessFile的seek函数的一些疑问?

seek就是查询的意思,可以根据文件中的字节进行查询数据(不知道这么说对不对)

下面这个函数中

    private void setThreadBreakpoint(
            File file, 
            File tempFile,
            long contentLength, 
            long[] startPos, 
            long[] endPos) {
        RandomAccessFile tempFileFos = null;
        try {
            if (file.exists()) {
                System.out.println("file " + fileName + " has exists!");

                long localFileSize = file.length();
                // 下载的目标文件已存在,判断目标文件是否完整
                if (localFileSize < contentLength) {
                    System.out.println("Now download continue ... ");

                    tempFileFos = new RandomAccessFile(tempFile, "rw");
                    // 遍历目标文件的所有临时文件,设置断点的位置,即每个临时文件的长度
                    for (int i = 0; i < threadNum; i++) {
                        tempFileFos.seek(4 + 24 * i + 8);
                        endPos[i] = tempFileFos.readLong();

                        tempFileFos.seek(4 + 24 * i + 16);
                        startPos[i] = tempFileFos.readLong();
                    }
                } else {
                    System.out.println("This file has download complete!");
                }

            } else {
                // 如果下载的目标文件不存在,则创建新文件
                file.createNewFile();
                tempFile.createNewFile();
                tempFileFos = new RandomAccessFile(tempFile, "rw");
                tempFileFos.writeInt(threadNum);

                for (int i = 0; i < threadNum; i++) {

                    // 创建子线程来负责下载数据,每段数据的起始位置为(threadLength * i)
                    startPos[i] = threadLength * i;
                    tempFileFos.writeLong(startPos[i]);

                    /*
                     * 设置子线程的终止位置,非最后一个线程即为(threadLength * (i + 1) - 1)
                     * 最后一个线程的终止位置即为下载内容的长度
                     */
                    if (i == threadNum - 1) {
                        endPos[i] = contentLength;
                    } else {
                        endPos[i] = threadLength * (i + 1) - 1;
                    }
                    // end position
                    tempFileFos.writeLong(endPos[i]);
                    // current position
                    tempFileFos.writeLong(startPos[i]);
                }
            }
        } catch (IOException e1) {
            e1.printStackTrace();
        } finally {
            try {
                tempFileFos.close();
            } catch (IOException e2) {
                e2.printStackTrace();
            }
        }
    }

这个循环方法体里

 // 遍历目标文件的所有临时文件,设置断点的位置,即每个临时文件的长度
                    for (int i = 0; i < threadNum; i++) {
                        tempFileFos.seek(4 + 24 * i + 8);
                        endPos[i] = tempFileFos.readLong();
                        tempFileFos.seek(4 + 24 * i + 16);
                        startPos[i] = tempFileFos.readLong();
                    }

这句话

 tempFileFos.seek(4 + 24 * i + 8);

这里面seek的参数是根据什么确定的?

1个回答

首先更正一下,seek函数的作用是从文件起始位置开始计算,将文件指针定位到seek所指向的位置。
这个临时文件的格式应该是:
线程数(4字节)
线程1起始位置(8字节)
线程1结束位置(8字节)
线程1当前位置(8字节)

线程2起始位置(8字节)
线程2结束位置(8字节)
线程2当前位置(8字节)

.....
线程n起始位置(8字节)
线程n结束位置(8字节)
线程n当前位置(8字节)

tempFileFos.seek(4 + 24 * i + 8); 的含义是偏移到:
线程数(4字节) + 24(起始位置8字节+结束位置8字节+当前位置8字节) × 当前第i个线程 + 线程i的起始位置8字节 = 当前第i个线程结束位置数据在文件中的偏移

tempFileFos.seek(4 + 24 * i + 16); 的含义是偏移到:
线程数(4字节) + 24(起始位置8字节+结束位置8字节+当前位置8字节) × 当前第i个线程 + 16(线程i的起始位置8字节 + 线程i的终止位置8字节) = 当前第i个线程当前位置数据在文件中的偏移

u013179958
CSDNRGY 回复tang_cheng: 为什么线程不能大于256,文件大小不能大于2G,这个是如何计算出来的?
大约 3 年之前 回复
tang_cheng
tang_cheng 线程数(2字节)要用short类型,线程n起始位置(4字节)要用int类型,如果你这么改的确seek参数可以这么计算,但是有一点限制:线程数不能大于256,文件长度不能大于2G。而且这种记录文件就这么几个字节,没必要为了省几个字节而使其兼容性变差
大约 3 年之前 回复
u013179958
CSDNRGY 线程数可以是n字节吗?起始位置、结束位置、当前位置都可以是n字节吗?
大约 3 年之前 回复
u013179958
CSDNRGY 那我想修改一下临时文件的格式,改成线程数(2字节)、线程n起始位置(4字节)、线程n结束位置(4字节)、线程n当前位置(4字节),那么seek中的参数就应该是seek(2 + 12 * i + 4);喽?
大约 3 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问