《Kotin 極簡教程》第15章 Kotlin 文件IO操作穿剖、正則表達式與多線程

第15章 Kotlin 文件IO操作與多線程


《Kotlin極簡教程》正式上架:

點擊這里 > 去京東商城購買閱讀

點擊這里 > 去天貓商城購買閱讀

非常感謝您親愛的讀者,大家請多支持K痢N诙省窟扑!有任何問題赋除,歡迎隨時與我交流~


我們在使用 Groovy 的文件 IO 操作的時候账劲,感覺非常便利戳护。同樣的Kotlin也有好用的文件 IO 操作的 API。同樣的在 Kotlin 中對 Java 的正則表達式功能做了一些實用的擴展瀑焦。還有 Kotlin 中的多線程主要也是對 Java 的多線程 API 作了一些封裝腌且。因為這些 Java 已經(jīng)有了很多的基礎(chǔ) API,Kotlin 并沒有自己再去重復(fù)實現(xiàn)榛瓮,而是在 Java 的基礎(chǔ)上進行了實用的功能擴展铺董。

本章我們就來介紹Kotlin 文件 IO 操作、正則表達式以及多線程相關(guān)的內(nèi)容禀晓。

15.1 Kotlin IO 簡介

Kotlin的IO操作都在kotlin.io包下柄粹。Kotlin的原則就是Java已經(jīng)有的,好用的就直接使用匆绣,沒有的或者不好用的驻右,就在原有類的基礎(chǔ)上進行封裝擴展,例如Kotlin 就給 File 類寫了擴展函數(shù)崎淳。這跟Groovy的擴展API 的思想是一樣的堪夭。

15.2 終端 IO

Java 超長的輸出語句 System.out.println() 居然延續(xù)到了現(xiàn)在!同樣的工作在C++里面只需要簡單的 cout<< 就可以完成拣凹。當(dāng)然森爽,如果需要的話,我們可以在工程中直接封裝 System.out.println() 為簡單的打印方法嚣镜。

在Kotlin里面很簡單爬迟,只需要使用println或者print這兩個全局函數(shù)即可,我們不再需要冗長的前綴菊匿。當(dāng)然如果我們很懷舊付呕,就是想用 System.out.println() 计福,Kotlin 依然支持直接這么使用(與 Java 無縫互操作)。

>>> System.out.println("K")
K
>>> println("K")
K

這里的 println 函數(shù)Kotlin實現(xiàn)如下

@kotlin.internal.InlineOnly
public inline fun println(message: Any?) {
    System.out.println(message)
}

當(dāng)然徽职,Kotlin 也只是在 System.out.println() 的基礎(chǔ)上進行了封裝象颖。

從終端讀取數(shù)據(jù)也很簡單,最基本的方法就是全局函數(shù)readLine姆钉,它直接從終端讀取一行作為字符串说订。如果需要更進一步的處理,可以使用Kotlin提供的各種字符串處理函數(shù)來處理和轉(zhuǎn)換字符串潮瓶。

Kotlin 的封裝終端IO 的類在 stdlib/src/kotlin/io/Console.kt 源文件中陶冷。

15.3 文件 IO 操作

Kotlin為java.io.File提供了大量好用的擴展函數(shù),這些擴展函數(shù)主要在下面三個源文件中:

kotlin/io/files/FileTreeWalk.kt
kotlin/io/files/Utils.kt
kotlin/io/FileReadWrite.kt

同時毯辅,Kotlin 也針對InputStream埂伦、OutputStream和 Reader 等都做了簡單的擴展。它們主要在下面的兩個源文件中:

kotlin/io/IOStreams.kt
kotlin/io/ReadWrite.kt

Koltin 的序列化直接采用的 Java 的序列化類的類型別名:

internal typealias Serializable = java.io.Serializable

下面我們來簡單介紹一下 Kotlin 文件讀寫操作悉罕。

15.3.1 讀文件

讀取文件全部內(nèi)容

我們?nèi)绻唵巫x取一個文件赤屋,可以使用readText()方法立镶,它直接返回整個文件內(nèi)容壁袄。代碼示例如下

    /**
     * 獲取文件全部內(nèi)容字符串
     * @param filename
     */
    fun getFileContent(filename: String): String {
        val f = File(filename)
        return f.readText(Charset.forName("UTF-8"))
    }

我們直接使用 File 對象來調(diào)用 readText 函數(shù)即可獲得該文件的全部內(nèi)容,它返回一個字符串媚媒。如果指定字符編碼嗜逻,可以通過傳入?yún)?shù)Charset來指定,默認是UTF-8編碼缭召。

如果我們想要獲得文件每行的內(nèi)容栈顷,可以簡單通過split("\n")來獲得一個每行內(nèi)容的數(shù)組。

獲取文件每行的內(nèi)容

我們也可以直接調(diào)用 Kotlin 封裝好的readLines函數(shù)嵌巷,獲得文件每行的內(nèi)容萄凤。readLines函數(shù)返回一個持有每行內(nèi)容的 List。

    /**
     * 獲取文件每一行內(nèi)容搪哪,存入一個 List 中
     * @param filename
     */
    fun getFileLines(filename: String): List<String> {
        return File(filename).readLines(Charset.forName("UTF-8"))
    }

直接操作字節(jié)數(shù)組

我們?nèi)绻M苯硬僮魑募淖止?jié)數(shù)組靡努,可以使用readBytes()。如果想使用傳統(tǒng)的Java方式晓折,在Kotlin 中你也可以像 Groovy 一樣自如使用惑朦。

    //讀取為bytes數(shù)組
    val bytes: ByteArray = f.readBytes()
    println(bytes.joinToString(separator = " "))

    //直接像 Java 中的那樣處理Reader或InputStream
    val reader: Reader = f.reader()
    val inputStream: InputStream = f.inputStream()
    val bufferedReader: BufferedReader = f.bufferedReader()
}

15.3.2 寫文件

和讀文件類似,寫入文件也很簡單漓概。我們可以寫入字符串漾月,也可以寫入字節(jié)流。還可以直接使用Java的 Writer 或者 OutputStream胃珍。

覆蓋寫文件

    fun writeFile(text: String, destFile: String) {
        val f = File(destFile)
        if (!f.exists()) {
            f.createNewFile()
        }
        f.writeText(text, Charset.defaultCharset())
    }

末尾追加寫文件

    fun appendFile(text: String, destFile: String) {
        val f = File(destFile)
        if (!f.exists()) {
            f.createNewFile()
        }
        f.appendText(text, Charset.defaultCharset())
    }

15.4 遍歷文件樹

和Groovy一樣梁肿,Kotlin也提供了方便的功能來遍歷文件樹蜓陌。遍歷文件樹需要調(diào)用擴展方法walk()。它會返回一個FileTreeWalk對象栈雳,它有一些方法用于設(shè)置遍歷方向和深度护奈,詳情參見FileTreeWalk API 文檔說明。

提示:FileTreeWalk API 文檔鏈接 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/-file-tree-walk/

下面的例子遍歷了指定文件夾下的所有文件哥纫。

    fun traverseFileTree(filename: String) {
        val f = File(filename)
        val fileTreeWalk = f.walk()
        fileTreeWalk.iterator().forEach { println(it.absolutePath) }
    }

測試代碼:

    @Test fun testTraverseFileTree() {
        KFileUtil.traverseFileTree(".")
    }

運行上面的測試代碼霉旗,它將輸出當(dāng)前目錄下的所有子目錄及其文件。

我們還可以遍歷當(dāng)前文件下面所有子目錄文件蛀骇,存入一個 Iterator<File> 中

    fun getFileIterator(filename: String): Iterator<File> {
        val f = File(filename)
        val fileTreeWalk = f.walk()
        return fileTreeWalk.iterator()
    }

我們遍歷當(dāng)前文件下面所有子目錄文件厌秒,還可以根據(jù)條件過濾,并把結(jié)果存入一個 Sequence<File> 中

    fun getFileSequenceBy(filename: String, p: (File) -> Boolean): Sequence<File> {
        val f = File(filename)
        return f.walk().filter(p)
    }

測試代碼:

    @Test fun testGetFileSequenceBy() {
        val fileSequence1 = KFileUtil.getFileSequenceBy(".", {
            it.isDirectory
        })
        fileSequence1.forEach { println("fileSequence1: ${it.absoluteFile} ") }

        val fileSequence2 = KFileUtil.getFileSequenceBy(".", {
            it.isFile
        })
        fileSequence2.forEach { println("fileSequence2: ${it.absoluteFile} ") }

        val fileSequence3 = KFileUtil.getFileSequenceBy(".", {
            it.extension == "kt"
        })
        fileSequence3.forEach { println("fileSequence3: ${it.absoluteFile} ") }
    }

在工程中運行上面的測試代碼擅憔,它將會有類似下面的輸出:

...
...

fileSequence3: /Users/jack/kotlin/chapter15_file_io/./src/main/kotlin/com/easy/kotlin/fileio/KFileUtil.kt 
fileSequence3: /Users/jack/kotlin/chapter15_file_io/./src/main/kotlin/com/easy/kotlin/fileio/KNetUtil.kt 
fileSequence3: /Users/jack/kotlin/chapter15_file_io/./src/main/kotlin/com/easy/kotlin/fileio/KShellUtil.kt 
fileSequence3: /Users/jack/kotlin/chapter15_file_io/./src/test/kotlin/com/easy/kotlin/fileio/KFileUtilTest.kt 


15.5 網(wǎng)絡(luò)IO操作

Kotlin為java.net.URL增加了兩個擴展方法鸵闪,readBytes和readText。我們可以方便的使用這兩個方法配合正則表達式實現(xiàn)網(wǎng)絡(luò)爬蟲的功能暑诸。

下面我們簡單寫幾個函數(shù)實例蚌讼。

根據(jù) url 獲取該 url 的響應(yīng) HTML函數(shù)


fun getUrlContent(url: String): String {
    return URL(url).readText(Charset.defaultCharset())
}

根據(jù) url 獲取該 url 響應(yīng)比特數(shù)組函數(shù)

fun getUrlBytes(url: String): ByteArray {
    return URL(url).readBytes()
}

把 url 響應(yīng)字節(jié)數(shù)組寫入文件

fun writeUrlBytesTo(filename: String, url: String) {
    val bytes = URL(url).readBytes()
    File(filename).writeBytes(bytes)
}

下面這個例子簡單的獲取了百度首頁的源代碼。

getUrlContent("https://www.baidu.com")

下面這個例子根據(jù) url 來獲取一張圖片的比特流个榕,然后調(diào)用readBytes()方法讀取到字節(jié)流并寫入文件篡石。

writeUrlBytesTo("圖片.jpg", "http://n.sinaimg.cn/default/4_img/uplaod/3933d981/20170622/2fIE-fyhfxph6601959.jpg")

在項目相應(yīng)文件夾下我們可以看到下載好的 “圖片.jpg” 。

15.6 kotlin.io標準庫

Kotlin 的 io 庫主要是擴展 Java 的 io 庫西采。下面我們簡單舉幾個例子凰萨。

appendBytes

追加字節(jié)數(shù)組到該文件中

方法簽名:

fun File.appendBytes(array: ByteArray)

appendText

追加文本到該文件中

方法簽名:


fun File.appendText(
    text: String, 
    charset: Charset = Charsets.UTF_8)

bufferedReader

獲取該文件的BufferedReader

方法簽名:

fun File.bufferedReader(
    charset: Charset = Charsets.UTF_8, 
    bufferSize: Int = DEFAULT_BUFFER_SIZE
): BufferedReader

bufferedWriter

獲取該文件的BufferedWriter

方法簽名:

fun File.bufferedWriter(
    charset: Charset = Charsets.UTF_8, 
    bufferSize: Int = DEFAULT_BUFFER_SIZE
): BufferedWriter

copyRecursively

復(fù)制該文件或者遞歸復(fù)制該目錄及其所有子文件到指定路徑,如果指定路徑下的文件不存在械馆,會自動創(chuàng)建胖眷。

方法簽名:

fun File.copyRecursively(
    target: File, 
    overwrite: Boolean = false, // 是否覆蓋。true:覆蓋之前先刪除原來的文件
    onError: (File, IOException) -> OnErrorAction = { _, exception -> throw exception }
): Boolean
提示: Kotlin 對 File 的擴展函數(shù) API 文檔https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-file/index.html
關(guān)于 kotlin.io 下面的API文檔在這里 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/index.html

15.7 執(zhí)行Shell命令行

我們使用 Groovy 的文件 IO 操作感覺非常好用霹崎,例如

package com.easy.kotlin

import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

@RunWith(JUnit4)
class ShellExecuteDemoTest {
    @Test
    def void testShellExecute() {
        def p = "ls -R".execute()
        def output = p.inputStream.text
        println(output)
        def fname = "我圖.url"
        def f = new File(fname)
        def lines = f.readLines()
        lines.forEach({
            println(it)
        })
        println(f.text)
    }
}

Kotlin 中的文件 IO珊搀,網(wǎng)絡(luò) IO 操作跟 Groovy一樣簡單。

另外尾菇,從上面的代碼中我們看到使用 Groovy 執(zhí)行終端命令非常簡單:

def p = "ls -R".execute()
def output = p.inputStream.text

在 Kotlin 中境析,目前還沒有對 String 類和 Process 擴展這樣的函數(shù)。其實擴展這樣的函數(shù)非常簡單错沽。我們完全可以自己擴展簿晓。

首先,我們來擴展 String 的 execute() 函數(shù)千埃。

fun String.execute(): Process {
    val runtime = Runtime.getRuntime()
    return runtime.exec(this)
}

然后憔儿,我們來給 Process 類擴展一個 text函數(shù)。

fun Process.text(): String {
    var output = ""
    //  輸出 Shell 執(zhí)行的結(jié)果
    val inputStream = this.inputStream
    val isr = InputStreamReader(inputStream)
    val reader = BufferedReader(isr)
    var line: String? = ""
    while (line != null) {
        line = reader.readLine()
        output += line + "\n"
    }
    return output
}

完成了上面兩個簡單的擴展函數(shù)之后放可,我們就可以在下面的測試代碼中谒臼,可以像 Groovy 一樣執(zhí)行終端命令了:

val p = "ls -al".execute()

val exitCode = p.waitFor()
val text = p.text()

println(exitCode)
println(text)

實際上朝刊,通過之前的很多實例的學(xué)習(xí),我們可以看出 Kotlin 的擴展函數(shù)相當(dāng)實用蜈缤。Kotlin 語言本身API 也大量使用了擴展功能拾氓。

15.8 正則表達式

我們在 Kotlin 中除了仍然可以使用 Java中的 Pattern,Matcher 等類之外底哥,Kotlin 還提供了一個正則表達式類 kotlin/text/regex/Regex.kt 咙鞍,我們通過 Regex 的構(gòu)造函數(shù)來創(chuàng)建一個正則表達式。

15.8.1 構(gòu)造 Regex 表達式

使用Regex構(gòu)造函數(shù)

>>> val r1 = Regex("[a-z]+")
>>> val r2 = Regex("[a-z]+", RegexOption.IGNORE_CASE)

其中的匹配選項 RegexOption 是直接使用的 Java 類 Pattern中的正則匹配選項趾徽。

使用 String 的 toRegex 擴展函數(shù)

>>> val r3 = "[A-Z]+".toRegex()

15.8.2 Regex 函數(shù)

Regex 里面提供了豐富的簡單而實用的函數(shù)续滋,如下表所示

函數(shù)名稱 功能說明
matches(input: CharSequence): Boolean 輸入字符串全部匹配
containsMatchIn(input: CharSequence): Boolean 輸入字符串至少有一個匹配
matchEntire(input: CharSequence): MatchResult? 輸入字符串全部匹配,返回一個匹配結(jié)果對象
replace(input: CharSequence, replacement: String): String 把輸入字符串中匹配的部分替換成replacement的內(nèi)容
replace(input: CharSequence, transform: (MatchResult) -> CharSequence): String 把輸入字符串中匹配到的值孵奶,用函數(shù) transform映射之后的新值替換
find(input: CharSequence, startIndex: Int = 0): MatchResult? 返回輸入字符串中第一個匹配的值
findAll(input: CharSequence, startIndex: Int = 0): Sequence<MatchResult> 返回輸入字符串中所有匹配的值MatchResult的序列

下面我們分別就上面的函數(shù)給出簡單實例疲酌。

matches

輸入字符串全部匹配正則表達式返回 true , 否則返回 false。

>>> val r1 = Regex("[a-z]+")
>>> r1.matches("ABCzxc")
false
>>> 

>>> val r2 = Regex("[a-z]+", RegexOption.IGNORE_CASE)
>>> r2.matches("ABCzxc")
true

>>> val r3 = "[A-Z]+".toRegex()
>>> r3.matches("GGMM")
true

containsMatchIn

輸入字符串中至少有一個匹配就返回true了袁,沒有一個匹配就返回false朗恳。

>>> val re = Regex("[0-9]+")
>>> re.containsMatchIn("012Abc")
true
>>> re.containsMatchIn("Abc")
false

matchEntire

輸入字符串全部匹配正則表達式返回 一個MatcherMatchResult對象,否則返回 null载绿。

>>> val re = Regex("[0-9]+")
>>> re.matchEntire("1234567890")
kotlin.text.MatcherMatchResult@34d713a2
>>> re.matchEntire("1234567890!")
null

我們可以訪問MatcherMatchResult的value熟悉來獲得匹配的值粥诫。

>>> re.matchEntire("1234567890")?.value
1234567890

由于 matchEntire 函數(shù)的返回是MatchResult? 可空對象,所以這里我們使用了安全調(diào)用符號 ?. 卢鹦。

replace(input: CharSequence, replacement: String): String

把輸入字符串中匹配的部分替換成replacement的內(nèi)容臀脏。

>>> val re = Regex("[0-9]+")
>>> re.replace("12345XYZ","abcd")
abcdXYZ

我們可以看到劝堪,"12345XYZ"中12345是匹配正則表達式 [0-9]+的內(nèi)容冀自,它被替換成了 abcd

replace(input: CharSequence, transform: (MatchResult) -> CharSequence): String

把輸入字符串中匹配到的值秒啦,用函數(shù) transform映射之后的新值替換熬粗。

>>> val re = Regex("[0-9]+")
>>> re.replace("9XYZ8", { (it.value.toInt() * it.value.toInt()).toString() })
81XYZ64

我們可以看到,9XYZ8中數(shù)字9和8是匹配正則表達式[0-9]+的內(nèi)容余境,它們分別被transform函數(shù)映射 (it.value.toInt() * it.value.toInt()).toString() 的新值 81 和 64 替換驻呐。

find

返回輸入字符串中第一個匹配的MatcherMatchResult對象。

>>> val re = Regex("[0-9]+")
>>> re.find("123XYZ987abcd7777")
kotlin.text.MatcherMatchResult@4d4436d0
>>> re.find("123XYZ987abcd7777")?.value
123

findAll

返回輸入字符串中所有匹配的值的MatchResult的序列芳来。

>>> val re = Regex("[0-9]+")
>>> re.findAll("123XYZ987abcd7777")
kotlin.sequences.GeneratorSequence@f245bdd

我們可以通過 forEach 循環(huán)遍歷所以匹配的值

>>> re.findAll("123XYZ987abcd7777").forEach{println(it.value)}
123
987
7777

15.8.3 使用 Java 正則表達式類

除了上面 Kotlin 提供的函數(shù)之外含末,我們在 Kotlin 中仍然可以使用 Java 的正則表達式的 API。

val re = Regex("[0-9]+")
val p = re.toPattern()
val m = p.matcher("888ABC999")
while (m.find()) {
    val d = m.group()
    println(d)
}

上面的代碼運行輸出:

888
999

15.9 Kotlin 的多線程

Kotlin中沒有synchronized關(guān)鍵字即舌。
Kotlin中沒有volatile關(guān)鍵字佣盒。
Kotlin的Any類似于Java的Object,但是沒有wait()顽聂,notify()和notifyAll() 方法肥惭。

那么并發(fā)如何在Kotlin中工作呢盯仪?放心,Kotlin 既然是站在 Java 的肩膀上蜜葱,當(dāng)然少不了對多線程編程的支持——Kotlin通過封裝 Java 中的線程類全景,簡化了我們的編碼。同時我們也可以使用一些特定的注解牵囤, 直接使用 Java 中的同步關(guān)鍵字等爸黄。下面我們簡單介紹一下使用Kotlin 進行多線程編程的相關(guān)內(nèi)容。

15.9.1 創(chuàng)建線程

我們在 Java中通常有兩種方法在Java中創(chuàng)建線程:

  • 擴展Thread類
  • 或者實例化它并通過構(gòu)造函數(shù)傳遞一個Runnable

因為我們可以很容易地在Kotlin中使用Java類揭鳞,這兩個方式都可以使用馆纳。

使用對象表達式創(chuàng)建

    object : Thread() {
        override fun run() {
            Thread.sleep(3000)
            println("A 使用 Thread 對象表達式: ${Thread.currentThread()}")
        }
    }.start()

此代碼使用Kotlin的對象表達式創(chuàng)建一個匿名類并覆蓋run()方法。

使用 Lambda 表達式

下面是如何將一個Runnable傳遞給一個新創(chuàng)建的Thread實例:

    Thread({
        Thread.sleep(2000)
        println("B 使用 Lambda 表達式: ${Thread.currentThread()}")
    }).start()

我們在這里看不到Runnable汹桦,在Kotlin中可以很方便的直接使用上面的Lambda表達式來表達鲁驶。

還有更簡單的方法嗎? 且看下文解說舞骆。

使用 Kotlin 封裝的 thread 函數(shù)

例如钥弯,我們寫了下面一段線程的代碼

    val t = Thread({
        Thread.sleep(2000)
        println("C 使用 Lambda 表達式:${Thread.currentThread()}")
    })
    t.isDaemon = false
    t.name = "CThread"
    t.priority = 3
    t.start()

后面的四行可以說是樣板化的代碼。在 Kotlin 中把這樣的操作封裝簡化了督禽。

    thread(start = true, isDaemon = false, name = "DThread", priority = 3) {
        Thread.sleep(1000)
        println("D 使用 Kotlin 封裝的函數(shù) thread(): ${Thread.currentThread()}")
    }

這樣的代碼顯得更加精簡整潔了脆霎。事實上,thread()函數(shù)就是對我們編程實踐中經(jīng)常用到的樣板化的代碼進行了抽象封裝狈惫,它的實現(xiàn)如下:

public fun thread(start: Boolean = true, isDaemon: Boolean = false, contextClassLoader: ClassLoader? = null, name: String? = null, priority: Int = -1, block: () -> Unit): Thread {
    val thread = object : Thread() {
        public override fun run() {
            block()
        }
    }
    if (isDaemon)
        thread.isDaemon = true
    if (priority > 0)
        thread.priority = priority
    if (name != null)
        thread.name = name
    if (contextClassLoader != null)
        thread.contextClassLoader = contextClassLoader
    if (start)
        thread.start()
    return thread
}

這只是一個非常方便的包裝函數(shù)睛蛛,簡單實用。從上面的例子我們可以看出胧谈,Kotlin 通過擴展 Java 的線程 API忆肾,簡化了樣板代碼。

15.9.2 同步方法和塊

synchronized不是Kotlin中的關(guān)鍵字菱肖,它替換為@Synchronized 注解客冈。 Kotlin中的同步方法的聲明將如下所示:

    @Synchronized fun appendFile(text: String, destFile: String) {
        val f = File(destFile)
        if (!f.exists()) {
            f.createNewFile()
        }
        f.appendText(text, Charset.defaultCharset())
    }

@Synchronized 注解與 Java中的 synchronized 具有相同的效果:它會將JVM方法標記為同步。 對于同步塊稳强,我們使用synchronized() 函數(shù)场仲,它使用鎖作為參數(shù):

    fun appendFileSync(text: String, destFile: String) {
        val f = File(destFile)
        if (!f.exists()) {
            f.createNewFile()
        }

        synchronized(this){
            f.appendText(text, Charset.defaultCharset())
        }
    }

跟 Java 基本一樣。

15.9.3 可變字段

同樣的退疫,Kotlin沒有 volatile 關(guān)鍵字渠缕,但是有@Volatile注解。

@Volatile private var running = false
fun start() {
    running = true
    thread(start = true) {
        while (running) {
            println("Still running: ${Thread.currentThread()}")
        }
    }
}

fun stop() {
    running = false
    println("Stopped: ${Thread.currentThread()}")
}

@Volatile會將JVM備份字段標記為volatile褒繁。

當(dāng)然亦鳞,在 Kotlin 中我們有更好用的協(xié)程并發(fā)庫。在代碼工程實踐中,我們可以根據(jù)實際情況自由選擇蚜迅。

本章小結(jié)

Kotlin 是一門工程實踐性很強的語言舵匾,從本章介紹的文件IO、正則表達式以及多線程等內(nèi)容中谁不,我們可以領(lǐng)會到 Kotlin 的基本原則:充分使用已有的 Java 生態(tài)庫坐梯,在此基礎(chǔ)之上進行更加簡單實用的擴展,大大提升程序員們的生產(chǎn)力刹帕。從中我們也體會到了Kotlin 編程中的極簡理念——不斷地抽象吵血、封裝、擴展偷溺,使之更加簡單實用蹋辅。

本章示例代碼:https://github.com/EasyKotlin/chapter15_file_io

另外,筆者綜合了本章的內(nèi)容挫掏,使用 SpringBoot + Kotlin 寫了一個簡單的圖片爬蟲 Web 應(yīng)用侦另,感興趣的讀者可參考源碼:https://github.com/EasyKotlin/chatper15_net_io_img_crawler

在下一章,也我們的最后一章中尉共,讓我們脫離 JVM褒傅,直接使用 Kotlin Native 來開發(fā)一個直接編譯成機器碼運行的 Kotlin 應(yīng)用程序。


Kotlin 開發(fā)者社區(qū)

國內(nèi)第一Kotlin 開發(fā)者社區(qū)公眾號袄友,主要分享殿托、交流 Kotlin 編程語言、Spring Boot剧蚣、Android支竹、React.js/Node.js、函數(shù)式編程鸠按、編程思想等相關(guān)主題礼搁。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市待诅,隨后出現(xiàn)的幾起案子叹坦,更是在濱河造成了極大的恐慌熊镣,老刑警劉巖卑雁,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異绪囱,居然都是意外死亡测蹲,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門鬼吵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扣甲,“玉大人,你說我怎么就攤上這事×鹜冢” “怎么了启泣?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長示辈。 經(jīng)常有香客問我寥茫,道長,這世上最難降的妖魔是什么矾麻? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任纱耻,我火速辦了婚禮,結(jié)果婚禮上险耀,老公的妹妹穿的比我還像新娘弄喘。我一直安慰自己,他們只是感情好甩牺,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布蘑志。 她就那樣靜靜地躺著,像睡著了一般贬派。 火紅的嫁衣襯著肌膚如雪卖漫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天赠群,我揣著相機與錄音羊始,去河邊找鬼。 笑死查描,一個胖子當(dāng)著我的面吹牛突委,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播冬三,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼匀油,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了勾笆?” 一聲冷哼從身側(cè)響起敌蚜,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窝爪,沒想到半個月后弛车,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡蒲每,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年纷跛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邀杏。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡贫奠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情唤崭,我是刑警寧澤拷恨,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站谢肾,受9級特大地震影響挑随,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜勒叠,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一兜挨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧眯分,春花似錦拌汇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至飘诗,卻和暖如春与倡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背昆稿。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工纺座, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人溉潭。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓净响,卻偏偏與公主長得像,于是被迫代替她去往敵國和親喳瓣。 傳聞我的和親對象是個殘疾皇子馋贤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 前言 人生苦多,快來 Kotlin 畏陕,快速學(xué)習(xí)Kotlin配乓! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,211評論 9 118
  • 第10章 Kotlin與Java互操作 《Kotlin極簡教程》正式上架: 點擊這里 > 去京東商城購買閱讀 點擊...
    光劍書架上的書閱讀 3,620評論 0 24
  • 1.在一個類里面創(chuàng)建"構(gòu)造方法" (第一個不帶參數(shù)的構(gòu)造方法)(第二個是帶參數(shù)的構(gòu)造方法) 2.析構(gòu)函數(shù)作用 -1...
    EdenChow閱讀 253評論 0 0
  • 笑著低頭惠毁,是一種豁達 與人相處要學(xué)會低頭犹芹,“得饒人處且饒人”。每個人都不是圣人仁讨,大家都有犯錯的可能羽莺,何必揪著別人的...
    Una笑笑閱讀 166評論 0 2
  • 契訶夫說 言簡意賅是天才的姊妹 看我寫的這么少就知道我是天才了吧
    kiran_閱讀 290評論 0 1