感謝Tenfour04 的大力幫助,我得到了處理 CSV 檔案的精彩代碼。
但是,我遇到了以下麻煩。
- 如何呼叫這些函式?
- 如何初始化二維陣列變數?
下面是最終作業的代碼。
MainActivity.kt
package com.surlofia.csv_tenfour04_1
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import java.io.File
import java.io.IOException
import com.surlofia.csv_tenfour04_1.databinding.ActivityMainBinding
var chk_Q_Num: MutableList<Int> = mutableListOf (
0,
1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20,
)
var chk_Q_State: MutableList<String> = mutableListOf (
"z",
"a", "b", "c", "d", "e",
"f", "g", "h", "i", "j"
)
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
// Load saved data at game startup. It will be invalid if performed by other activities.
val filePath = filesDir.path "/chk_Q.csv"
val file = File(filePath)
binding.fileExists.text = isFileExists(file).toString()
if (isFileExists(file)) {
val csvIN = file.readAsCSV()
for (i in 0 .. 10) {
chk_Q_Num[i] = csvIN[i][0].toInt()
chk_Q_State[i] = csvIN[i][1]
}
}
// Game Program Run
val csvOUT = mutableListOf(
mutableListOf("0","OK"),
mutableListOf("1","OK"),
mutableListOf("2","OK"),
mutableListOf("3","Not yet"),
mutableListOf("4","Not yet"),
mutableListOf("5","Not yet"),
mutableListOf("6","Not yet"),
mutableListOf("7","Not yet"),
mutableListOf("8","Not yet"),
mutableListOf("9","Not yet"),
mutableListOf("10","Not yet")
)
var tempString = ""
for (i in 0 .. 10) {
csvOUT[i][0] = chk_Q_Num[i].toString()
csvOUT[i][1] = "OK"
tempString = tempString csvOUT[i][0] "-->" csvOUT[i][1] "\n"
}
binding.readFile.text = tempString
// and save Data
file.writeAsCSV(csvOUT)
}
// https://www.techiedelight.com/ja/check-if-a-file-exists-in-kotlin/
private fun isFileExists(file: File): Boolean {
return file.exists() && !file.isDirectory
}
@Throws(IOException::class)
fun File.readAsCSV(): List<List<String>> {
val splitLines = mutableListOf<List<String>>()
forEachLine {
splitLines = it.split(", ")
}
return splitLines
}
@Throws(IOException::class)
fun File.writeAsCSV(values: List<List<String>>) {
val csv = values.joinToString("\n") { line -> line.joinToString(", ") }
writeText(csv)
}
}
chk_Q.csv
0,0
1,OK
2,OK
3,Not yet
4,Not yet
5,Not yet
6,Not yet
7,Not yet
8,Not yet
9,Not yet
10,Not yet
1.如何呼叫這些函式?
下面的代碼似乎運行良好。我是否以正確的方式呼叫這些函式?還是有更好的方法來實作這一目標?
讀
if (isFileExists(file)) {
val csvIN = file.readAsCSV()
for (i in 0 .. 10) {
chk_Q_Num[i] = csvIN[i][0].toInt()
chk_Q_State[i] = csvIN[i][1]
}
}
寫
file.writeAsCSV(csvOUT)
2、如何初始化二維陣列變數?
val csvOUT = mutableListOf(
mutableListOf("0","OK"),
mutableListOf("1","OK"),
mutableListOf("2","OK"),
mutableListOf("3","Not yet"),
mutableListOf("4","Not yet"),
mutableListOf("5","Not yet"),
mutableListOf("6","Not yet"),
mutableListOf("7","Not yet"),
mutableListOf("8","Not yet"),
mutableListOf("9","Not yet"),
mutableListOf("10","Not yet")
)
我想知道使用 for 回圈而不是一個一個地撰寫特定值的聰明方法。
例如,像下面這樣。
val csvOUT = mutableListOf(mutableListOf())
for (i in 0 .. 10) {
csvOUT[i][0] = i
csvOUT[i][1] = "OK"
}
但這給了我以下錯誤訊息:
沒有足夠的資訊來推斷型別變數 T
如果您能提供一個如何為初學者執行此操作的示例,那就太好了。
----- 2022年6月15日添加。 ----- [問題1]關于初始化,執行以下代碼時出現錯誤“繼續停止”。應用程式被強制終止。為什么是這樣?
val csvOUT: MutableList<MutableList<String>> = mutableListOf(mutableListOf())
for (i in 0 .. 10) {
csvOUT[i][0] = "$i"
csvOUT[i][1] = "OK"
}
[錯誤資訊]
java.lang.RuntimeException:無法啟動活動 ComponentInfo{com.surlofia.csv_endzeit_01/com.surlofia.csv_endzeit_01.MainActivity}:java.lang.IndexOutOfBoundsException:索引:0,大小:0
uj5u.com熱心網友回復:
在我看來,您的問題基本上有兩個部分。首先,您需要了解 Kotlin 型別系統,包括泛型。其次,您需要一些有關解決手頭問題的方法的知識。
型別系統和泛型
mutableListOf您使用的函式是通用的,因此需要一個型別引數,從檔案T中可以看出它的定義:
fun <T> mutableListOf(): MutableList<T>
大多數時候,Kotlin 編譯器非常擅長型別推斷,即根據背景關系猜測使用的型別。例如,我不需要在以下示例中顯式提供型別,因為 Kotlin 編譯器可以從使用背景關系推斷型別。
val listWithInts = mutableListOf(3, 7)
推斷的型別是MutableList<Int>. 然而,有時這可能不是人們想要的。例如,我可能希望null在上面的串列中允許值。為了實作這一點,我必須告訴編譯器它不僅應該允許Int串列中的值,還應該允許值null,將型別從Intto擴大Int?。我至少可以通過兩種方式實作這一目標。
- 提供泛型型別引數
val listWithNullableInts = mutableListOf<Int?>(3, 7)
- 明確定義預期的回傳型別
val listWithNullableInts: MutableList<Int?> = mutableListOf(3, 7)
在您的情況下,編譯器沒有足夠的資訊來從使用背景關系推斷型別。因此,您必須為其提供該背景關系,例如通過將特定型別的值傳遞給函式或使用上面提到的兩個選項之一。
多維陣列的初始化
StackOverflow 上已經有關于在 Kotlin 中創建多維陣列的問題和答案。
您手頭的問題的一種解決方案可能如下。
val csvOUT: MutableList<MutableList<String>> = mutableListOf(mutableListOf())
for (i in 0 .. 10) {
csvOUT[i][0] = "$i"
csvOUT[i][1] = "OK"
}
您通過顯式定義預期的回傳型別來幫助 Kotlin 編譯器,然后將值作為Strings 添加到您的 2D 串列中。
如果尺寸是固定的,您可能希望使用固定大小的Array來代替。
val csvArray = Array(11) { index -> arrayOf("$index", "OK") }
然而,在這兩種解決方案中,您都將Int索引轉換為 a String。如果您要為每個級別存盤的唯一資訊是 a String,您不妨使用一個簡單的List<String并使用每個條目的索引作為級別編號,例如:
val csvOut = List(11) { "OK" }
val levelThree = csvOut[2] // first index of List is 0
這也適用于更復雜的資料結構而不是Strings. 你只需要調整你fun File.writeAsCSV(values: List<List<String>>)的接受不同的型別作為values引數。假設一個簡單的資料類,您最終可能會得到以下內容:
data class LevelState(val state: String, val timeBeaten: Instant?)
val levelState = List(11) { LevelState("OK", Instant.now()) }
fun File.writeAsCSV(values: List<LevelState>) {
val csvString = values
.mapIndexed { index, levelState -> "$index, ${levelState.state}, ${levelState.timeBeaten}" }
.joinToString("\n")
writeText(csvString)
}
Array如果您更喜歡更“經典”的命令式方法,您可以List使用像for in.
val list: MutableList<MutableList<String>> = mutableListOf() // list is now []
for (i in 0..10) {
val innerList = mutableListOf())
innerList.add("$i")
innerList.add("OK")
innerList.add("${Instant.now()}")
list.add(innerList)
// list is after first iteration [ ["0", "OK", "2022-06-15T07:03:14.315Z"] ]
}
該語法listName[index] = value只是運算子的運算子多載的語法糖,例如set,請參閱MutableList 上的檔案。
您無法訪問之前未填充的索引,例如在串列初始化期間或使用add; 否則你會收到一個IndexOutOfBoundsException.
如果要使用set運算子,一種選擇是使用預先填充的陣列,如下所示:
val array: Array<Array<String>>> = Array(11) {
Array(3) { "default" }
} // array is [ ["default, "default", "default"], ...]
array[1][2] = "myValue"
但是,我不推薦這種方法,因為它可能會導致剩余的、可能無效的初始資料,以防錯過替換值。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/491262.html
