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())
}
|
小檔案
文字讀取
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)
}
|
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
}
}
|
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())
}
|
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)
}
}
}
|
forEachLine
只能簡單輸出資料。
1
2
3
4
5
6
7
| @Test
fun test14() {
val file = File("/Users/cici/testc/file_test")
file.forEachLine { line ->
println(line)
}
}
|
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)
}
}
}
|
釋放資源
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()
}
}
|