Last active
November 5, 2024 09:46
-
-
Save unclebean/c7e831fb2496ce41a5139788b67516c1 to your computer and use it in GitHub Desktop.
tiff2pdf_kotlin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import kotlinx.coroutines.* | |
| import java.io.File | |
| fun main() { | |
| val tiffFiles = listOf("file1.tif", "file2.tif", "file3.tif") // List of TIFF file paths | |
| val outputDir = "output/" // Directory where PDFs will be saved | |
| runBlocking { | |
| // Run each conversion in parallel using coroutines | |
| val conversionJobs = tiffFiles.map { tiffFile -> | |
| async { | |
| convertTiffToPdf(tiffFile, outputDir) | |
| } | |
| } | |
| // Wait for all conversions to complete | |
| conversionJobs.awaitAll() | |
| } | |
| println("All TIFF files converted to PDF.") | |
| } | |
| // Function to convert a single TIFF file to PDF using a command-line tool | |
| suspend fun convertTiffToPdf(tiffFilePath: String, outputDir: String) = withContext(Dispatchers.IO) { | |
| val pdfFilePath = "$outputDir${File(tiffFilePath).nameWithoutExtension}.pdf" | |
| val command = listOf("tiff2pdf", "-o", pdfFilePath, tiffFilePath) // Adjust the command if necessary | |
| try { | |
| val process = ProcessBuilder(command) | |
| .redirectErrorStream(true) | |
| .start() | |
| // Wait for the command to finish | |
| process.waitFor() | |
| // Check if the conversion was successful | |
| if (process.exitValue() == 0) { | |
| println("Converted $tiffFilePath to $pdfFilePath") | |
| } else { | |
| println("Failed to convert $tiffFilePath") | |
| } | |
| } catch (e: Exception) { | |
| println("Error converting $tiffFilePath: ${e.message}") | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.io.File | |
| fun main() { | |
| val file = File("path/to/your/file.dat") | |
| val regex = """checkSum":\s*"([^"]*)"""".toRegex() | |
| file.forEachLine { line -> | |
| val matchResult = regex.find(line) | |
| if (matchResult != null) { | |
| val checkSumValue = matchResult.groupValues[1] | |
| println("Extracted checkSum value: $checkSumValue") | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.io.File | |
| import java.io.FileInputStream | |
| import java.io.FileOutputStream | |
| import java.nio.file.Files | |
| import java.nio.file.Path | |
| import java.nio.file.StandardCopyOption | |
| import java.util.zip.ZipEntry | |
| import java.util.zip.ZipInputStream | |
| import java.util.zip.ZipOutputStream | |
| object FileUtils { | |
| // Function to create a directory | |
| fun createDirectory(path: String): Boolean { | |
| val dir = File(path) | |
| return if (!dir.exists()) { | |
| dir.mkdirs() | |
| } else { | |
| false | |
| } | |
| } | |
| // Function to delete a directory recursively | |
| fun deleteDirectory(path: String): Boolean { | |
| val dir = File(path) | |
| return if (dir.exists()) { | |
| dir.deleteRecursively() | |
| } else { | |
| false | |
| } | |
| } | |
| // Function to move a directory | |
| fun moveDirectory(srcPath: String, destPath: String): Boolean { | |
| val srcDir = Path.of(srcPath) | |
| val destDir = Path.of(destPath) | |
| return try { | |
| Files.move(srcDir, destDir, StandardCopyOption.REPLACE_EXISTING) | |
| true | |
| } catch (e: Exception) { | |
| e.printStackTrace() | |
| false | |
| } | |
| } | |
| // Function to zip a directory or file | |
| fun zip(srcPath: String, destZipPath: String) { | |
| val srcFile = File(srcPath) | |
| ZipOutputStream(FileOutputStream(destZipPath)).use { zos -> | |
| zipFile(srcFile, srcFile.name, zos) | |
| } | |
| } | |
| private fun zipFile(fileToZip: File, fileName: String, zos: ZipOutputStream) { | |
| if (fileToZip.isHidden) return | |
| if (fileToZip.isDirectory) { | |
| val children = fileToZip.listFiles() | |
| children?.forEach { childFile -> | |
| zipFile(childFile, "$fileName/${childFile.name}", zos) | |
| } | |
| return | |
| } | |
| FileInputStream(fileToZip).use { fis -> | |
| val zipEntry = ZipEntry(fileName) | |
| zos.putNextEntry(zipEntry) | |
| fis.copyTo(zos) | |
| } | |
| } | |
| // Function to unzip a zip file | |
| fun unzip(zipFilePath: String, destDirPath: String) { | |
| val destDir = File(destDirPath) | |
| if (!destDir.exists()) destDir.mkdirs() | |
| ZipInputStream(FileInputStream(zipFilePath)).use { zis -> | |
| var entry: ZipEntry? = zis.nextEntry | |
| while (entry != null) { | |
| val newFile = File(destDir, entry.name) | |
| if (entry.isDirectory) { | |
| newFile.mkdirs() | |
| } else { | |
| File(newFile.parent).mkdirs() | |
| FileOutputStream(newFile).use { fos -> | |
| zis.copyTo(fos) | |
| } | |
| } | |
| zis.closeEntry() | |
| entry = zis.nextEntry | |
| } | |
| } | |
| } | |
| fun copyFileToBackup(sourcePath: String, backupFolderPath: String): Boolean { | |
| return try { | |
| // Create File objects from the paths | |
| val sourceFile = File(sourcePath) | |
| if (!sourceFile.exists()) { | |
| println("Source file does not exist: $sourcePath") | |
| return false | |
| } | |
| // Define the destination path in the backup folder | |
| val destFile = File(backupFolderPath, sourceFile.name) | |
| // Ensure the backup folder exists | |
| destFile.parentFile?.mkdirs() | |
| // Copy the file with REPLACE_EXISTING to overwrite if it already exists in the backup folder | |
| Files.copy(sourceFile.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING) | |
| println("File copied to backup successfully!") | |
| true | |
| } catch (e: Exception) { | |
| e.printStackTrace() // Print any exceptions for debugging | |
| false // Return false if an error occurs | |
| } | |
| } | |
| fun findSingleZipFileWithId(directoryPath: String, id: String): File? { | |
| val directory = File(directoryPath) | |
| // Check if the directory exists and is indeed a directory | |
| if (!directory.exists() || !directory.isDirectory) { | |
| logError("Invalid directory path: $directoryPath") | |
| return null | |
| } | |
| // Find zip files that contain the specified ID in their name | |
| val matchingFiles = directory.listFiles { file -> | |
| file.isFile && file.extension == "zip" && file.name.contains(id) | |
| } | |
| return when { | |
| matchingFiles == null || matchingFiles.isEmpty() -> { | |
| logError("No zip file found with ID: $id in directory: $directoryPath") | |
| null | |
| } | |
| matchingFiles.size > 1 -> { | |
| logError("Multiple zip files found with ID: $id in directory: $directoryPath. Only one file expected.") | |
| null | |
| } | |
| else -> matchingFiles[0] // Return the single matching file | |
| } | |
| } | |
| fun zipFolderContents(sourceDirPath: String, zipFilePath: String) { | |
| val sourceDir = File(sourceDirPath) | |
| val zipFile = File(zipFilePath) | |
| FileOutputStream(zipFile).use { fos -> | |
| ZipOutputStream(fos).use { zos -> | |
| sourceDir.listFiles()?.forEach { file -> | |
| zipFileOrDirectory(file, "", zos) | |
| } | |
| } | |
| } | |
| } | |
| fun zipFileOrDirectory(file: File, parentPath: String, zos: ZipOutputStream) { | |
| val entryName = if (parentPath.isEmpty()) file.name else "$parentPath/${file.name}" | |
| if (file.isDirectory) { | |
| file.listFiles()?.forEach { childFile -> | |
| zipFileOrDirectory(childFile, entryName, zos) | |
| } | |
| } else { | |
| FileInputStream(file).use { fis -> | |
| val zipEntry = ZipEntry(entryName) | |
| zos.putNextEntry(zipEntry) | |
| fis.copyTo(zos) | |
| zos.closeEntry() | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <dependency> | |
| <groupId>org.flywaydb</groupId> | |
| <artifactId>flyway-core</artifactId> | |
| <version>9.16.0</version> <!-- Use the latest version --> | |
| </dependency> | |
| <dependency> | |
| <groupId>org.postgresql</groupId> | |
| <artifactId>postgresql</artifactId> | |
| <version>42.6.0</version> <!-- Use the latest version --> | |
| </dependency> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| fun calculateMD5Checksum(filePath: String): String? { | |
| val processBuilder = ProcessBuilder("md5sum", filePath) | |
| processBuilder.redirectErrorStream(true) | |
| val process = processBuilder.start() | |
| // Read the output of the command | |
| val reader = BufferedReader(InputStreamReader(process.inputStream)) | |
| val output = reader.readLine() | |
| reader.close() | |
| // Wait for the process to finish | |
| process.waitFor() | |
| // Extract and return the checksum value (first part of the output) | |
| return output?.split(" ")?.firstOrNull() | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <configuration> | |
| <property name="LOG_FILE" value="${log.file:-default.log}"/> | |
| <!-- Service Log Appender --> | |
| <appender name="SERVICE_LOG" class="ch.qos.logback.core.FileAppender"> | |
| <file>${LOG_FILE}/service.log</file> | |
| <encoder> | |
| <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> | |
| </encoder> | |
| </appender> | |
| <!-- Audit Log Appender --> | |
| <appender name="AUDIT_LOG" class="ch.qos.logback.core.FileAppender"> | |
| <file>${LOG_FILE}/audit.log</file> | |
| <encoder> | |
| <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> | |
| </encoder> | |
| </appender> | |
| <!-- Root Logger for general application logging --> | |
| <root level="INFO"> | |
| <appender-ref ref="SERVICE_LOG"/> | |
| </root> | |
| <!-- Separate Logger for Audit functionality --> | |
| <logger name="com.yourpackage.audit" level="INFO" additivity="false"> | |
| <appender-ref ref="AUDIT_LOG"/> | |
| </logger> | |
| </configuration> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| fun main(args: Array<String>) { | |
| // Expecting the path to the properties file as the first command-line argument | |
| if (args.isEmpty()) { | |
| println("Please provide the path to the properties file.") | |
| return | |
| } | |
| val propertiesFilePath = args[0] | |
| val properties = loadProperties(propertiesFilePath) | |
| // Access individual properties | |
| val inputFilePath = properties.getProperty("inputFilePath") ?: throw IllegalArgumentException("inputFilePath not found") | |
| val outputDirectory = properties.getProperty("outputDirectory") ?: throw IllegalArgumentException("outputDirectory not found") | |
| val logLevel = properties.getProperty("logLevel") ?: "INFO" // Default to INFO if not set | |
| val timeout = properties.getProperty("timeout")?.toIntOrNull() ?: 60 // Default to 60 if not set or invalid | |
| // Use the properties in your tool | |
| println("Input File Path: $inputFilePath") | |
| println("Output Directory: $outputDirectory") | |
| println("Log Level: $logLevel") | |
| println("Timeout: $timeout") | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <dependency> | |
| <groupId>io.github.microutils</groupId> | |
| <artifactId>kotlin-logging-jvm</artifactId> | |
| <version>3.0.5</version> | |
| </dependency> | |
| <dependency> | |
| <groupId>ch.qos.logback</groupId> | |
| <artifactId>logback-classic</artifactId> | |
| <version>1.4.5</version> | |
| </dependency> | |
| <dependency> | |
| <groupId>com.github.doyaaaaaken</groupId> | |
| <artifactId>kotlin-csv-jvm</artifactId> | |
| <version>1.2.0</version> | |
| </dependency> | |
| <dependency> | |
| <groupId>org.jetbrains.kotlinx</groupId> | |
| <artifactId>kotlinx-coroutines-core</artifactId> | |
| <version>1.6.4</version> | |
| </dependency> | |
| <project> | |
| <!-- Your existing project configuration --> | |
| <build> | |
| <plugins> | |
| <!-- Maven Shade Plugin for creating a fat JAR --> | |
| <plugin> | |
| <groupId>org.apache.maven.plugins</groupId> | |
| <artifactId>maven-shade-plugin</artifactId> | |
| <version>3.2.4</version> | |
| <executions> | |
| <execution> | |
| <phase>package</phase> | |
| <goals> | |
| <goal>shade</goal> | |
| </goals> | |
| <configuration> | |
| <createDependencyReducedPom>false</createDependencyReducedPom> | |
| <transformers> | |
| <!-- Set the main class in the manifest --> | |
| <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> | |
| <mainClass>MainKt</mainClass> <!-- Replace with your actual main class path --> | |
| </transformer> | |
| </transformers> | |
| </configuration> | |
| </execution> | |
| </executions> | |
| </plugin> | |
| </plugins> | |
| </build> | |
| </project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import com.github.doyaaaaaken.kotlincsv.dsl.csvReader | |
| import java.io.File | |
| data class CsvEntry(val parentZip: String, val count: Int, val tifFiles: List<String>) | |
| fun readCsv(filePath: String): List<CsvEntry> { | |
| val rows = csvReader().readAllWithHeader(File(filePath)) | |
| return rows.map { row -> | |
| val parentZip = row["parent_zip"] ?: "" | |
| val count = row["count"]?.toIntOrNull() ?: 0 | |
| val tifFiles = row["tif_files"]?.split(",")?.map { it.trim() } ?: emptyList() | |
| CsvEntry(parentZip, count, tifFiles) | |
| } | |
| } | |
| fun main(args: Array<String>) { | |
| if (args.isEmpty()) { | |
| println("Please provide the path to the CSV file as a command-line argument.") | |
| return | |
| } | |
| val filePath = args[0] | |
| if (!File(filePath).exists()) { | |
| println("The file at path '$filePath' does not exist.") | |
| return | |
| } | |
| val entries = readCsv(filePath) | |
| entries.forEach { entry -> | |
| println("Parent Zip: ${entry.parentZip}, Count: ${entry.count}, TIF Files: ${entry.tifFiles}") | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.io.FileInputStream | |
| import java.util.Properties | |
| fun loadProperties(filePath: String): Properties { | |
| val properties = Properties() | |
| FileInputStream(filePath).use { inputStream -> | |
| properties.load(inputStream) | |
| } | |
| return properties | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| fun parseCsvColumnToList(input: String): List<Int> { | |
| // Remove any surrounding quotes and brackets | |
| val trimmedInput = input.trim().removeSurrounding("[", "]").removeSurrounding("\"") | |
| // Split by commas and map to integers, logging conversion failures | |
| return trimmedInput.split(",").mapNotNull { element -> | |
| try { | |
| element.trim().toInt() | |
| } catch (e: NumberFormatException) { | |
| logger.error("Failed to convert '$element' to Int", e) | |
| null | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import kotlinx.coroutines.* | |
| import mu.KotlinLogging | |
| import java.io.File | |
| import java.io.FileInputStream | |
| import java.io.FileOutputStream | |
| import java.nio.file.Files | |
| import java.security.MessageDigest | |
| import java.util.concurrent.Executors | |
| import java.util.zip.ZipEntry | |
| import java.util.zip.ZipFile | |
| import java.util.zip.ZipOutputStream | |
| import kotlin.io.path.ExperimentalPathApi | |
| import kotlin.io.path.createTempDirectory | |
| import kotlin.io.path.deleteRecursively | |
| private val logger = KotlinLogging.logger {} | |
| @OptIn(ExperimentalPathApi::class) | |
| fun main() { | |
| val csvFiles = listOf("path/to/csv1.csv", "path/to/csv2.csv") // Add paths to your CSV files here | |
| val executor = Executors.newFixedThreadPool(csvFiles.size) // Create a thread for each CSV file | |
| csvFiles.forEach { csvFile -> | |
| executor.submit { | |
| runBlocking { | |
| processCsvFile(csvFile) | |
| } | |
| } | |
| } | |
| executor.shutdown() | |
| } | |
| suspend fun processCsvFile(csvFilePath: String) = coroutineScope { | |
| logger.info { "Processing CSV file: $csvFilePath" } | |
| val tempDir = createTempDirectory("zipProcessing_${File(csvFilePath).nameWithoutExtension}") | |
| try { | |
| val entries = parseCsvFile(csvFilePath) // Parse CSV for zip and TIFF file paths | |
| val zipJobs = entries.map { entry -> | |
| async { | |
| processZipEntry(entry.zipFilePath, entry.tiffFiles, tempDir) | |
| } | |
| } | |
| zipJobs.awaitAll() // Wait for all zip files for this CSV to complete | |
| } finally { | |
| tempDir.deleteRecursively() | |
| logger.info { "Cleaned up temporary directory for CSV: $csvFilePath" } | |
| } | |
| } | |
| suspend fun processZipEntry(zipFilePath: String, tiffFiles: List<String>, tempDir: java.nio.file.Path) = coroutineScope { | |
| logger.info { "Processing zip file: $zipFilePath" } | |
| val zipDir = Files.createTempDirectory(tempDir, "zip_${File(zipFilePath).nameWithoutExtension}") | |
| unzip(File(zipFilePath), zipDir.toFile()) | |
| val convertJobs = tiffFiles.map { tiffFile -> | |
| async { | |
| val tiffPath = zipDir.resolve(tiffFile).toFile() | |
| val pdfFile = File(tiffPath.parent, "${tiffPath.nameWithoutExtension}.pdf") | |
| convertTiffToPdf(tiffPath, pdfFile) | |
| tiffPath.delete() | |
| logger.info { "Converted and replaced TIFF file: ${tiffFile.name}" } | |
| } | |
| } | |
| convertJobs.awaitAll() // Wait for all conversions in this zip to complete | |
| val modifiedZip = File(tempDir.toFile(), File(zipFilePath).name) | |
| zipDirectory(zipDir.toFile(), modifiedZip) | |
| logger.info { "Recreated modified zip: ${modifiedZip.absolutePath}" } | |
| zipDir.deleteRecursively() | |
| logger.info { "Cleaned up temporary extraction directory for zip: $zipFilePath" } | |
| } | |
| fun unzip(zipFile: File, destDir: File) { /* Same as before */ } | |
| suspend fun convertTiffToPdf(tiffFile: File, pdfFile: File) = withContext(Dispatchers.IO) { /* Same as before */ } | |
| fun zipDirectory(sourceDir: File, zipFile: File) { /* Same as before */ } | |
| fun calculateChecksum(file: File): String { /* Same as before */ } | |
| fun parseCsvFile(csvFilePath: String): List<ZipEntryData> { /* Parse CSV to retrieve file paths */ } | |
| data class ZipEntryData(val zipFilePath: String, val tiffFiles: List<String>) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| fun updateCheckSum(filePath: String, newCheckSum: String) { | |
| val file = File(filePath) | |
| val regex = """("checkSum":\s*")([^"]*)(")""".toRegex() | |
| // Read the entire content of the file | |
| val content = file.readText() | |
| // Replace the old checksum value with the new one | |
| val updatedContent = regex.replace(content) { | |
| // it.groupValues[1] captures "checkSum": " | |
| // it.groupValues[3] captures the trailing quote after the old checksum value | |
| "${it.groupValues[1]}$newCheckSum${it.groupValues[3]}" | |
| } | |
| // Write the updated content back to the file | |
| file.writeText(updatedContent) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment