29f35c4a创建于 2025年1月27日历史提交
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2024. All rights reserved.
 */
package zip4cj.io.inputstream

import std.fs.OpenMode

func getFileModle(mode: String): OpenMode {
    if (mode == "rw") {
        return OpenMode.ReadWrite
    } else if (mode == "r") {
        return OpenMode.Read
    } else {
        return OpenMode.Write
    }
}

public func initializeRandomAccessFileForHeaderReading(zipFile: Path): RandomAccessFile {
    if (FileUtils.isNumberedSplitFile(zipFile)) {
        var allSplitFiles = FileUtils.getAllSortedNumberedSplitFiles(zipFile)
        var numberedSplitRandomAccessFile = NumberedSplitRandomAccessFile(zipFile,
            RandomAccessFileMode.READ.getValue(), allSplitFiles)
        numberedSplitRandomAccessFile.openLastSplitFileForReading()
        return numberedSplitRandomAccessFile
    }
    if (!exists(zipFile)) {
        File.create(zipFile)
    }
    return RandomAccessFile(zipFile, OpenMode.ReadWrite)
}


class NumberedSplitRandomAccessFile <: RandomAccessFile {
    private var splitLength: Int64
    private var allSortedSplitFiles: Array<Path>
    private var randomAccessFile: RandomAccessFile
    private var singleByteBuffer = Array<Byte>(1, repeat: 0)
    private var currentOpenSplitFileCounter: Int64 = 0
    private var rwMode: String

    public init(file: Path, mode: String, allSortedSplitFiles: Array<Path>) {
        super(file, getFileModle(mode))
        this.rawFile.close()

        if (RandomAccessFileMode.WRITE.getValue() == mode) {
            throw IllegalArgumentException("write mode is not allowed for NumberedSplitRandomAccessFile")
        }

        assertAllSplitFilesExist(allSortedSplitFiles)
        this.randomAccessFile = RandomAccessFile(file, getFileModle(mode))
        this.allSortedSplitFiles = allSortedSplitFiles
        this.splitLength = this.rawFile.length
        this.rwMode = mode
    }

    public func read(b: Array<Byte>): Int64 {
        return read(b, 0, b.size)
    }

    public func read(b: Array<Byte>, off: Int64, len: Int64): Int64 {
        var readLen = randomAccessFile.read(b, off, len)

        if (readLen == -1) {
            if (currentOpenSplitFileCounter == allSortedSplitFiles.size - 1) {
                return -1
            }
            openRandomAccessFileForIndex(currentOpenSplitFileCounter + 1)
            return read(b, off, len)
        }

        return readLen
    }

    public func seek(pos: Int64) {
        var splitPartOfPosition = (pos / splitLength)

        if (splitPartOfPosition != currentOpenSplitFileCounter) {
            openRandomAccessFileForIndex(splitPartOfPosition)
        }

        randomAccessFile.seek(pos - (splitPartOfPosition * splitLength))
    }

    public func getFilePointer(): Int64 {
        return randomAccessFile.getFilePointer()
    }

    public prop length: Int64 {
        get() {
            return randomAccessFile.length
        }
    }

    public func close() {
        randomAccessFile.close()
        super.close()
    }

    func seekInCurrentPart(pos: Int64) {
        randomAccessFile.seek(pos)
    }

    public func openLastSplitFileForReading() {
        openRandomAccessFileForIndex(allSortedSplitFiles.size - 1)
    }

    private func openRandomAccessFileForIndex(splitCounter: Int64) {
        if (currentOpenSplitFileCounter == splitCounter) {
            return
        }

        if (splitCounter > allSortedSplitFiles.size - 1) {
            throw ZipIOException("split counter greater than number of split files")
        }

        randomAccessFile.close()
        randomAccessFile = RandomAccessFile(allSortedSplitFiles[splitCounter], getFileModle(rwMode))
        currentOpenSplitFileCounter = splitCounter
    }

    private static func assertAllSplitFilesExist(allSortedSplitFiles: Array<Path>) {
        allSortedSplitFiles
        return
    }
}