added cli tool
This commit is contained in:
126
cli/src/main/kotlin/net/woggioni/jzstd/Cli.kt
Normal file
126
cli/src/main/kotlin/net/woggioni/jzstd/Cli.kt
Normal file
@@ -0,0 +1,126 @@
|
||||
package net.woggioni.jzstd
|
||||
|
||||
import com.beust.jcommander.JCommander
|
||||
import com.beust.jcommander.Parameter
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
|
||||
object Cli {
|
||||
|
||||
private data class Params(
|
||||
@Parameter
|
||||
var parameters: List<String> = ArrayList(),
|
||||
|
||||
@Parameter(names = arrayOf("-c", "--stdout"), description = "Output to stdout")
|
||||
var console: Boolean = false,
|
||||
|
||||
@Parameter(names = arrayOf("-d", "--decompress"), description = "Decompress input")
|
||||
var decompress: Boolean = false,
|
||||
|
||||
@Parameter(names = arrayOf("-z", "--compress"), description = "Compress input")
|
||||
var compress: Boolean = false,
|
||||
|
||||
@Parameter(names = arrayOf("-k", "--keep"), description = "Keep input file")
|
||||
var keep: Boolean = false,
|
||||
|
||||
@Parameter(names = arrayOf("-f", "--overwrite"), description = "Overwrite destination")
|
||||
var overwrite: Boolean = false,
|
||||
|
||||
@Parameter(names = arrayOf("-l", "--level"), description = "Set compression level")
|
||||
var level: Int = 3,
|
||||
|
||||
@Parameter(names = arrayOf("-i", "--input"), description = "Set input file, defaults to stdin otherwise")
|
||||
var input: String? = null,
|
||||
|
||||
@Parameter(names = arrayOf("-o", "--output"), description = "Set output file")
|
||||
var output: String? = null,
|
||||
|
||||
@Parameter(names = arrayOf("-h", "--help"), help = true)
|
||||
var help: Boolean = false
|
||||
)
|
||||
|
||||
|
||||
val log = LoggerFactory.getLogger(Cli::class.java)
|
||||
|
||||
private fun fileNameWithoutExtension(fileName: String) = fileName.let {
|
||||
when (val dotIndex = it.lastIndexOf('.')) {
|
||||
-1 -> it
|
||||
else -> it.substring(0, dotIndex)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun main(argv: Array<String>) {
|
||||
val params = Params()
|
||||
val jc = JCommander.newBuilder()
|
||||
.addObject(params)
|
||||
.build()
|
||||
jc.parse(*argv)
|
||||
if (params.help) {
|
||||
jc.usage()
|
||||
return
|
||||
}
|
||||
if (!params.compress && !params.decompress) params.compress = true
|
||||
try {
|
||||
val input: InputStream = (params.input
|
||||
?.let { Paths.get(it) }
|
||||
?.let { Files.newInputStream(it) }
|
||||
?: System.`in`)
|
||||
.let {
|
||||
if (params.decompress) ZstdInputStream.from(it)
|
||||
else it
|
||||
}
|
||||
input.use { inputStream ->
|
||||
val output: OutputStream = (params.output.let {
|
||||
when (it) {
|
||||
null -> if (params.input == null || params.console) {
|
||||
null
|
||||
} else {
|
||||
when {
|
||||
params.compress && params.decompress ->
|
||||
throw IllegalArgumentException("Only one between --compress or --decompress must be selected")
|
||||
params.compress -> {
|
||||
Paths.get(params.input + ".zst")
|
||||
}
|
||||
params.decompress -> {
|
||||
val inputFile = Paths.get(params.input)
|
||||
val inputDir = inputFile.parent ?: Paths.get(".")
|
||||
inputDir.resolve(fileNameWithoutExtension(inputFile.fileName.toString()))
|
||||
}
|
||||
else -> {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> Paths.get(it)
|
||||
}
|
||||
}?.also { destination ->
|
||||
if (!params.overwrite && Files.exists(destination)) {
|
||||
throw IllegalStateException("Destination file $destination already exists")
|
||||
}
|
||||
}?.let {
|
||||
Files.newOutputStream(it)
|
||||
} ?: System.out).let {
|
||||
if (params.compress) ZstdOutputStream.from(it, params.level)
|
||||
else it
|
||||
}
|
||||
output.use { outputStream ->
|
||||
val buffer = ByteArray(0x10000)
|
||||
while (true) {
|
||||
val read = inputStream.read(buffer, 0, buffer.size)
|
||||
if (read < 0) break
|
||||
outputStream.write(buffer, 0, read)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (params.input != null && params.output == null && !params.console && !params.keep) Files.delete(Paths.get(params.input))
|
||||
} catch (t: Throwable) {
|
||||
log.error(t.message, t)
|
||||
}
|
||||
}
|
||||
}
|
17
cli/src/main/resources/log4j2.xml
Normal file
17
cli/src/main/resources/log4j2.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="WARN">
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_ERR">
|
||||
<PatternLayout pattern="%d{HH:mm:ss,SSS} %highlight{[%p]} (%t) %c: %m%n"/>
|
||||
<Filters>
|
||||
<ThresholdFilter level="INFO" onMatch="ACCEPT" />
|
||||
</Filters>
|
||||
</Console>
|
||||
</Appenders>
|
||||
|
||||
<Loggers>
|
||||
<Root level="ALL">
|
||||
<AppenderRef ref="Console"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
22
cli/src/test/kotlin/InsaneTest.kt
Normal file
22
cli/src/test/kotlin/InsaneTest.kt
Normal file
@@ -0,0 +1,22 @@
|
||||
import net.woggioni.jzstd.ZstdOutputStream
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
|
||||
class InsaneTest {
|
||||
|
||||
@Test
|
||||
fun test2() {
|
||||
val inputFile = Paths.get("/tmp/Richard_Dawkins_The_Selfish_Gene.pdf")
|
||||
Files.newInputStream(inputFile).use { `is` ->
|
||||
ZstdOutputStream.from(Files.newOutputStream(Paths.get("/tmp/Richard_Dawkins_The_Selfish_Gene.pdf.zst"))).use { os ->
|
||||
val buffer = ByteArray(0x10000)
|
||||
while (true) {
|
||||
val read = `is`.read(buffer)
|
||||
if (read < 0) break
|
||||
os.write(buffer, 0, read)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user