File

檔案語法

1
val file = File("/Users/cici/testc/file_test")

取得檔案大小

1
2
    val file = File("/Users/cici/testc/file_test")
    println(file.length())

字串與Byte互轉

byte轉成字串,第二個參數是編碼。

1
2
val str = String(bytes)
val str = String(bytes, Charsets.UTF_8)

有開始位置與結束位置。

1
2
val str = String(buffer, 0, len)
val str = String(buffer, 0, len, Charsets.UTF_8)

字串轉成byte。

1
2
val str = "Nice to see you."
val bytes = str.toByteArray()

Int轉成字元、轉成byte。

1
2
3
4
5
6
@Test
fun test8() {
  val data = 97
  println(data.toChar())
  println(data.toByte())
}
a
97

小檔案

文字讀取

1
2
3
4
5
  @Test
  fun test1() {
    val file = File("/Users/cici/testc/file_test")
    println(file.readText())
  }

文字寫入(覆蓋)

1
2
3
4
5
6
  @Test
  fun test3() {
    val file = File("/Users/cici/testc/file_test")
    file.writeText("Hello World!")
    println(file.readText())
  }

文字寫入(未覆蓋)

1
2
3
4
5
6
  @Test
  fun test4() {
    val file = File("/Users/cici/testc/file_test")
    file.appendText("Nice to see you.")
    println(file.readText())
  }

byte讀取

輸出檔案大小

1
2
3
4
5
6
  @Test
  fun test2() {
    val file = File("/Users/cici/testc/file_test")
    val bytes = file.readBytes()
    println(bytes.size)
  }
30

byte寫入(覆蓋)

1
2
3
4
5
6
  @Test
  fun test5() {
    val file = File("/Users/cici/testc/file_test")
    file.writeBytes("Nice to see you.".toByteArray())
    println(file.readText())
  }

byte寫入(未覆蓋)

1
2
3
4
5
6
  @Test
  fun test5() {
    val file = File("/Users/cici/testc/file_test")
    file.appendBytes("Nice to see you.".toByteArray())
    println(file.readText())
  }

use

使用use擴展函式,若物件有實作Closeable,結束時,就可以使用use自動呼叫物件.close()方法。

1
2
3
val file = File("/Users/cici/testc/file_test")
file.inputStream().use { input ->
}

use原始碼如下:僅截取close()的程式碼

1
2
3
4
5
6
7
8
9
10
11
when {
    apiVersionIsAtLeast(1, 1, 0) -> this.closeFinally(exception)
    this == null -> {}
    exception == null -> close()
    else ->
        try {
            close()
        } catch (closeException: Throwable) {
            // cause.addSuppressed(closeException) // ignored here
        }
}

inputStream

read() 回傳值是資料

一次讀取一個byte,但直接強制轉型成Int。

read()有資料,回傳 0-255。

read()沒資料,檔案結尾,回傳 -1。

read().also() 將read()回傳值當作參數,傳入also() 函式中,所以it是read()回傳值,把回傳值 設給 data變數,並把read()回傳值作為return值。

把read()傳回值,設給data變數。

1
input.read().also { data = it }

read()回傳值作為return值,並判斷return值是否為-1檔案結尾。

1
while (input.read().also { data = it } != -1) { }

完整程式碼

1
2
3
4
5
6
7
8
9
10
  @Test
  fun test6() {
    val file = File("/Users/cici/testc/file_test")
    file.inputStream().use { input ->
      var data: Int
      while (input.read().also { data = it } != -1) {
        print("${data.toChar()} ")
      }
    }
  }
H e l l o   W o r l d ! N i c e   t o   s e e   y o u . N i c e   t o   s e e   y o u . 

read(buffer) 回傳值是讀取到的大小

使用ByteArray()建立暫存空間。

注意!回傳值是讀取到的大小,不是資料!!!

資料存在buffer變數中。

buffer變數為資料暫存的區域,len為每次讀到的大小。

以下buffer的大小為1024 byte。

1
2
3
4
5
6
7
8
9
10
11
  @Test
  fun test7() {
    val file = File("/Users/cici/testc/file_test")
    file.inputStream().use { input ->
      val buffer = ByteArray(1024)
      var len: Int
      while (input.read(buffer).also { len = it } != -1) {
        print("${String(buffer, 0, len)} ")
      }
    }
  }
Hello World!Nice to see you.Nice to see you.

outputStream 寫入byte

目前標準作法是outputStream()一定要包在inputStream(),並使用2個use。

1
2
3
4
5
6
7
val file = File("/Users/cici/testc/file_test")
val file2 = File("/Users/cici/testc/file_test2")
file.inputStream().use { input ->
  file2.outputStream().use { output ->
      // 程式碼要寫這
  }
}

完整程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
fun test9() {
  val file = File("/Users/cici/testc/file_test")
  val file2 = File("/Users/cici/testc/file_test2")
  file.inputStream().use { input ->
    file2.outputStream().use { output ->
      val buffer = ByteArray(1024)
      var len: Int
      while (input.read(buffer).also { len = it } != -1) {
        output.write(buffer, 0 , len)
      }
    }
  }
  println(file2.readText())
}

copyTo

先前的寫法改成copyTo。

1
2
3
4
5
6
7
8
9
10
11
  @Test
  fun test10() {
    val file = File("/Users/cici/testc/file_test")
    val file2 = File("/Users/cici/testc/file_test2")
    file.inputStream().use { input ->
      file2.outputStream().use { output ->
        input.copyTo(output)
      }
    }
    println(file2.readText())
  }

bufferReader bufferedWriter

一行行讀取,注意是 != null 不是 != -1
讀取出來的資料型態是String。

1
2
3
4
5
6
7
8
9
10
  @Test
  fun test11() {
    val file = File("/Users/cici/testc/file_test")
    file.bufferedReader().use { reader ->
      var line: String
      while (reader.readLine().also { line = it } != null) {
        println("$line ")
      }
    }
  }

一行行寫入。可以使用newLine()。

1
2
3
4
5
6
7
8
9
10
  @Test
  fun test12() {
    val file = File("/Users/cici/testc/file_test")
    file.bufferedWriter().use { writer ->
      writer.write("test!")
      writer.newLine()
      writer.write("test2!")
    }
    println(file.readText())
  }
test!
test2!

useLines

可以處理大檔案、自動關閉檔案,把每一行字串轉成Sequence

1
2
3
val result = file.useLines { lines: Sequence<String> ->

}

讀取每一行文字

1
2
3
4
5
6
7
8
9
@Test
fun test13() {
  val file = File("/Users/cici/testc/file_test")
  file.useLines { lines ->
    lines.forEach { line ->
      println(line)
    }
  }
}
test!
test2!

forEachLine

只能簡單輸出資料。

1
2
3
4
5
6
7
  @Test
  fun test14() {
    val file = File("/Users/cici/testc/file_test")
    file.forEachLine { line ->
      println(line)
    }
  }
test!
test2!

Java型的寫法(不建議)

1
2
3
4
5
6
7
8
9
10
11
@Test
fun coroutin23() = runBlocking {
  var br = BufferedReader(FileReader("/Users/cici/testc/file_test"))
  br.use {
    var line: String?
    while (true) {
      line = it.readLine() ?: break
      println(line)
    }
  }
}
測試程式

java程式設計

釋放資源

finally是不管如何都會執行,可在finally中釋放資源。

1
2
3
4
5
6
7
8
9
  @Test
  fun coroutin22() = runBlocking {
    var br: BufferedReader? = null
    try {
      br = BufferedReader(FileReader("/Users/cici/testc/file_test"))
    } finally {
      br?.close()
    }
  }

results matching ""

    No results matching ""