/*
* Copyright (c) Huawei Technologies Co., Ltd. 2022-2024. All rights reserved.
*/
package zip4cj.tasks
public class ExtractFileTask <: AbstractExtractFileTask<ExtractFileTaskParameters> {
private var password: ?Array<Rune>
private var splitInputStream: ?SplitFileInputStream = None
public ExtractFileTask(
zipModel: ZipModel,
password: ?Array<Rune>,
unzipParameters: UnzipParameters,
asyncTaskParameters: AsyncTaskParameters
) {
super(zipModel, unzipParameters, asyncTaskParameters)
this.password = password
}
protected func executeTask(taskParameters: ExtractFileTaskParameters, progressMonitor: ProgressMonitor) {
let fileHeadersUnderDirectory = getFileHeadersToExtract(taskParameters.fileToExtract)
try (zipInputStream = createZipInputStream(taskParameters.zip4cjConfig)) {
var readBuff = Array<Byte>(taskParameters.zip4cjConfig.getBufferSize(), repeat: 0)
for (i in 0..fileHeadersUnderDirectory.size) {
let fileHeader = fileHeadersUnderDirectory[i]
splitInputStream.getOrThrow().prepareExtractionForFileHeader(fileHeader)
var newFileName = determineNewFileName(taskParameters.newFileName.getOrThrow(), taskParameters.fileToExtract,
fileHeader)
extractFile(zipInputStream, fileHeader, taskParameters.outputPath, newFileName, progressMonitor,
readBuff)
}
} finally {
if (let Some(v) <- splitInputStream) {
v.close()
}
}
}
protected func calculateTotalWork(taskParameters: ExtractFileTaskParameters): Int64 {
var fileHeadersUnderDirectory = getFileHeadersToExtract(taskParameters.fileToExtract)
return HeaderUtil.getTotalUncompressedSizeOfAllFileHeaders(fileHeadersUnderDirectory)
}
private func getFileHeadersToExtract(fileNameToExtract: String): ArrayList<FileHeader> {
if (!FileUtils.isZipEntryDirectory(fileNameToExtract)) {
var fileHeader = HeaderUtil.getFileHeader(getZipModel(), fileNameToExtract)
if (fileHeader.isNone()) {
throw ZipException("No file found with name " + fileNameToExtract + " in zip file", FILE_NOT_FOUND)
}
return ArrayList<FileHeader>([fileHeader.getOrThrow()])
}
return HeaderUtil.getFileHeadersUnderDirectory(
getZipModel().getCentralDirectory().getOrThrow().getFileHeaders(),
fileNameToExtract
)
}
private func createZipInputStream(zip4cjConfig: Zip4cjConfig): ZipInputStream {
splitInputStream = UnzipUtil.createSplitInputStream(getZipModel())
return ZipInputStream(splitInputStream.getOrThrow(), password: password, config: zip4cjConfig)
}
private func determineNewFileName(
newFileName: String,
fileNameToExtract: String,
fileHeaderBeingExtracted: FileHeader
): String {
if (!Zip4cjUtil.isStringNotNullAndNotEmpty(newFileName)) {
return newFileName
}
if (!FileUtils.isZipEntryDirectory(fileNameToExtract)) {
return newFileName
}
var fileSeparator = InternalZipConstants.ZIP_FILE_SEPARATOR
if (newFileName.endsWith(InternalZipConstants.ZIP_FILE_SEPARATOR)) {
fileSeparator = ""
}
let str = fileHeaderBeingExtracted.getFileName().getOrThrow()
var arr = str.split(fileNameToExtract, 2)
return "${arr[0]}${newFileName + fileSeparator}${arr[1]}"
}
}