感謝 Tenfour04 的大力幫助,我得到了處理 CSV 檔案的精彩代碼。 Kotlin 如何讀寫 CSV 檔案
但是,我遇到了以下麻煩。
[1] 如何呼叫這些函式。
[2] 如何初始化二維陣列變數。
下面是最終作業的代碼。
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)
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@ id/fileExists"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Hello World!"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@ id/readFile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@ id/fileExists" />
</androidx.constraintlayout.widget.ConstraintLayout>
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
build.gradle(:app)
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 33
buildToolsVersion '33.0.0'
defaultConfig {
applicationId "com.surlofia.csv_tenfour04_1"
minSdk 23
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.8.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
[1] 如何呼叫這些函式。
[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]
}
}
[2] 寫
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
如果您能提供一個如何為初學者執行此操作的示例,那就太好了。
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)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/489596.html
