Implementarea cat cu Kotlin Native
- 4 minute de citit
- 9 exemple de cod în Kotlin și Shell
- 2 imagini
Disponibil și în English
Pe această pagină

Introducere
Salut! 👋
În acest articol vom implementa utilitarul de linie de comandă cat, folosit în multe sisteme asemănătoare Unix, cum ar fi Linux și macOS.
Pentru implementare vom folosi Kotlin și vom renunța la Java Virtual Machine (JVM). Vom construi
un binar direct cu Kotlin Native. La final vom obține un
executabil pe care îl putem rula simplu pe un calculator Linux sau macOS.
Ce este cat?
Utilitarul cat are scopul de a concatena fișiere. Îl poți folosi tastând cat file.txt și va afișa
conținutul fișierului în terminal. Are și mai multe opțiuni, precum: usage: cat [-belnstuv] [file ...], care
sunt documentate în paginile de manual.
Kotlin și Kotlin Native

Kotlin este un limbaj de programare modern, lansat pentru prima dată de JetBrains în 2011 și susținut oficial mai târziu de Google pentru dezvoltarea de aplicații Android. Este proiectat să fie complet interoperabil cu Java, rezolvând în același timp unele dintre problemele frecvente ale Java, făcându-l mai concis, mai expresiv și mai plăcut de folosit.
Kotlin Native este o tehnologie pentru compilarea codului Kotlin în binare native, care pot rula fără o mașină virtuală precum Java Virtual Machine (JVM). Face parte din Kotlin Multiplatform, care este o tehnologie concepută pentru a simplifica dezvoltarea multiplatformă. Poți folosi Kotlin Multiplatform pentru a dezvolta software pentru Server, Android, iOS, Desktop și Web - JavaScript.
Implementarea cat cu Kotlin Native
Ca să urmărești pașii, îți recomand să folosești mediul de dezvoltare integrat (IDE) IntelliJ IDEA Community sau Professional.
Clonarea șablonului Kotlin Native
Începe prin a clona șablonul de proiect Kotlin Native. Eu am pregătit totul, ca să poți începe imediat.
git clone https://github.com/Kotlin/kmp-native-wizard k-catApoi deschide proiectul în IDE.
Modificarea șablonului
Am început modificarea șablonului prin schimbarea numelui proiectului în k-cat.
Deschide .../IdeaProjects/k-cat/settings.gradle.kts și setează rootProject.name
rootProject.name = "k-cat"Și cam atât am nevoie deocamdată ca să dăm proiectului nostru un nume potrivit! 🔩
Implementarea cat
Utilitarul cat este un program complex. Vom implementa o versiune simplificată, care are următoarele cerințe.
Cerințe
Programul acceptă un parametru de tip șir obligatoriu, implicit, care reprezintă calea către fișier,
și un parametru opțional de tip flag, -n.
Va deschide fișierul indicat prin parametrul cu calea și va afișa conținutul său pe ecranul terminalului.
Când este apelat cu parametrul opțional -n, va afișa numărul liniei înainte de conținutul fișierului.
Exemplu de utilizare:
./k-cat.kexe -n file.txt0 Hello,1 From nuculabs.dev Implementarea
Pentru a începe implementarea, deschide: .../IdeaProjects/k-cat/src/nativeMain/kotlin/Main.kt.
Citirea argumentelor din linia de comandă
Pentru a citi argumentele din linia de comandă, trebuie să adăugăm parametrul args: Array<String> la funcția main. Array-ul args
va conține argumentele din linia de comandă transmise programului.
fun main(args: Array<String>) { //...}Analizarea argumentelor din linia de comandă
Pentru a analiza argumentele din linia de comandă, am folosit construcții simple din Kotlin.
Codul se explică aproape singur. Mai întâi căutăm argumentul obligatoriu filePath, apoi îi stocăm
valoarea într-o variabilă. În al doilea rând, căutăm argumentul opțional în forma scurtă -n și în forma lungă --numbering, și
dacă este găsit în array-ul argumentelor din linia de comandă, setăm variabila booleană numbering pe true.
// Preia argumentul obligatoriu al căii fișierului val fileArgs = args.filterNot { it.startsWith("-") } if (fileArgs.size != 1) { println("Usage: missing path to file: ./k-cat <file>") return } val filePath = fileArgs.first() // Analizează argumentul opțional `-n` var numbering = false; args.forEach { when (it) { "-n" -> numbering = true "--numbering" -> numbering = true } }Citirea fișierelor
Citirea fișierelor se poate face folosind o funcție deja disponibilă sau cu ajutorul unei biblioteci. Eu am ales a doua variantă și am adăugat dependența okio în proiect.
Pentru a adăuga o dependență, deschide .../IdeaProjects/k-cat/build.gradle.kts și modifică sourceSets astfel:
kotlin { //... sourceSets { val nativeMain by getting val nativeTest by getting val commonMain by getting { dependencies { implementation("com.squareup.okio:okio:3.7.0") } } }}Apoi poți importa și folosi biblioteca în funcția main pentru a citi fișiere. De exemplu:
import okio.FileSystemimport okio.Path.Companion.toPathimport okio.useimport okio.bufferFileSystem.SYSTEM.source("file.txt".toPath()).use { fileSource -> fileSource.buffer().use { bufferedFileSource -> while (true) { val line = bufferedFileSource.readUtf8Line() ?: break // fă ceva cu linia } }}Implementarea unui k-cat simplu
Implementarea este acum simplă, deoarece știm cum să analizăm argumentele din linia de comandă și cum să citim fișiere.
Următorul bloc de cod implementează k-cat. Citește toate liniile dintr-o cale de fișier și, dacă numbering este true, afișează
numărul liniei și linia, altfel afișează doar linia.
FileSystem.SYSTEM.source(filePath.toPath()).use { fileSource -> fileSource.buffer().use { bufferedFileSource -> var number = 0 while (true) { val line = bufferedFileSource.readUtf8Line() ?: break if (numbering) { val formattedNumber = number.toString().padEnd(2, ' ') println("$formattedNumber $line") } else { println(line) } number += 1 } } }Concluzie
Pe scurt, Kotlin Native extinde capabilitățile Kotlin, permițând dezvoltatorilor să compileze cod Kotlin în binare native pentru o varietate de platforme, inclusiv desktop, web, Android, iOS și sisteme embedded. Această extensie oferă performanța aplicațiilor native, păstrând în același timp expresivitatea și funcțiile de siguranță ale Kotlin.
Mulțumesc că ai citit! Sărbători fericite! 🎄✨
Lectură suplimentară / Referințe
- https://kotlinlang.org/docs/native-get-started.html#build-and-run-the-application
- https://kotlinlang.org/docs/native-overview.html
- https://github.com/Kotlin/kmp-native-wizard
Codul complet: Main.kt
import okio.FileSystemimport okio.Path.Companion.toPathimport okio.useimport okio.bufferfun main(args: Array<String>) { // Preia argumentul obligatoriu al căii fișierului val fileArgs = args.filterNot { it.startsWith("-") } if (fileArgs.size != 1) { println("Usage: missing path to file: ./k-cat <file>") return } val filePath = fileArgs.first() // Analizează argumentul opțional `-n` var numbering = false; args.forEach { when (it) { "-n" -> numbering = true "--numbering" -> numbering = true } } FileSystem.SYSTEM.source(filePath.toPath()).use { fileSource -> fileSource.buffer().use { bufferedFileSource -> var number = 0 while (true) { val line = bufferedFileSource.readUtf8Line() ?: break if (numbering) { val formattedNumber = number.toString().padEnd(2, ' ') println("$formattedNumber $line") } else { println(line) } number += 1 } } }}