简体   繁体   English

Kotlin 如何读写 CSV 文件

[英]Kotlin How to read and write CSV file

Could you give me most simple code in Kotlin ?你能给我最简单的 Kotlin 代码吗?

I tried to find good example in seraching with Google, after 5 hours or more, I could NOT find what I want.我试图找到用谷歌搜索的好例子,5 小时或更长时间后,我找不到我想要的东西。

I can't find any code that I can copy and paste that will work by doing a Google search.我找不到任何可以通过 Google 搜索复制和粘贴的代码。

Nor can I find any applicable description in books.我在书中也找不到任何适用的描述。

This may be easy for intermediate or advanced users, but for me it is difficult.这对于中级或高级用户来说可能很容易,但对我来说很难。

If you are willing to explain this for beginners, please share your time.如果您愿意为初学者解释这一点,请分享您的时间。

I would like to update done marks for solved Quiz like this photo.我想像这张照片一样更新已解决测验的完成标记。

from chk[1] to chk[20]

not yet : 0
done : 2 
// 2 is similar Victory Sign.

for example, if solved Quiz Number "1"例如,如果解决了测验编号“1”

chk[1] = 2

var chk_Q: Array<Int> = arrayOf (
    0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
)

Now, while app is active, keep data 0 or 2. However, once app finished, chk_Q 1 to [20] back to 0.现在,当应用程序处于活动状态时,保留数据 0 或 2。但是,一旦应用程序完成,chk_Q 1到 [20] 就会回到 0。

So, I would like to save data in checkDone.csv.所以,我想将数据保存在 checkDone.csv 中。

My textbook not explained how to save and read CSV file.我的教科书没有解释如何保存和读取 CSV 文件。

Bellow code is not worked as I want.波纹管代码没有按我的意愿工作。

openFileOutput("checkDone.csv", MODE_PRIVATE)
         .bufferedWriter().use {
             for (i in 1..10) {
                 it.write(chk_Q[i].toString())
             }
         }
openFileInput("checkDone.csv", MODE_PRIVATE)
        .bufferedReader().forEachLine {
            str.append(it)
            str.append(System.getProperty("line.separator"))
        }

=================================================== ==================================================== =

<Add on Thr 2 June 2022> <2022 年 6 月 2 日添加>

With Text File is done使用文本文件完成

=================================================== ==================================================== =

MainActivity.kt MainActivity.kt

=================================================== ==================================================== =

package com.surlofia.csv_exists_write_read

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.surlofia.csv_exists_write_read.databinding.ActivityMainBinding
import java.io.*

var chk_Q: Array<Int> = arrayOf (
    0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
)

class MainActivity : AppCompatActivity() {

    // View Binding Class のインスタンス
    // lateinit で宣言し初期化タイミングを onCreate() まで遅らせる
    // activity_main.xml の場合、ActivityMainBinding
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // setContentView(R.layout.activity_main) をコメントに変えた

        // bindingのイニシャライズ
        // super.onCreate(savedInstanceState) 直下に書く!!
        // Binding Classに含まれる静的 inflate() メソッドを呼び出す
        binding = ActivityMainBinding.inflate(layoutInflater)

        // root view への参照を取得
        val view = binding.root

        // view をsetContentView()にセット
        setContentView(view)

        // bindingのイニシャライズ 完了


        // Android - ファイル入出力の例(Read、Write、内部、外部ストレージ)
        // https://codechacha.com/ja/android-read-write-file/

    // Load saved data at game startup.
    // ゲーム起動時に、セーブデータを読み込んでおく
    val filePath = filesDir.path + "/memo.dat"
    val file = File(filePath)

    if (isFileExists(file)) {
        readTextFromFile(filePath)
    }

    // Game Program Run

    // and save Data
    writeTextToFile(filePath)

        binding.fileExists.text = isFileExists(file).toString()


    }



    // Kotlinにファイルが存在するかどうかを確認します
    // https://www.techiedelight.com/ja/check-if-a-file-exists-in-kotlin/

    private fun isFileExists(file: File): Boolean {
        return file.exists() && !file.isDirectory
    }


    // Android - ファイル入出力の例(Read、Write、内部、外部ストレージ)
    // https://codechacha.com/ja/android-read-write-file/
    // &
    // TECHNICAL MASTER はじめてのAndroidアプリ開発 Kotlin編 (TECHNICAL MASTER 98)
    // https://www.amazon.co.jp/dp/B09MHF7F6N/ref=dp_kinw_strp_1

    private fun readTextFromFile(path: String) {
        val file = File(path)
        val fileReader = FileReader(file)
        val bufferedReader = BufferedReader(fileReader)

        /*
        val readString = StringBuilder()

        bufferedReader.forEachLine {
            readString.append(it)
            readString.append(System.getProperty("line.separator"))
        }

        binding.readFile.text = readString

         */

        // Let'sプログラミング
        // Home › Java入門 › テキストファイルの入出力
        // まとめてテキストを読む
        // https://www.javadrive.jp/start/stream/index3.html

        chk_Q[0] = 0

        for (i in 1 .. 20) {
            chk_Q[i] = bufferedReader.readLine().toInt()
        }
        bufferedReader.close()


        var tempString = ""

        for(i in 0 .. 20) {
            tempString = tempString +i + "-->" + chk_Q[i] + "\n"
        }

        binding.readFile.text = tempString

    }

    // Android - ファイル入出力の例(Read、Write、内部、外部ストレージ)
    // https://codechacha.com/ja/android-read-write-file/

    private fun writeTextToFile(path: String) {
        val file = File(path)
        val fileWriter = FileWriter(file, false)
        val bufferedWriter = BufferedWriter(fileWriter)


        for (i in 0 .. 20) {
            chk_Q[i] = 2
            bufferedWriter.append(chk_Q[i].toString())
            bufferedWriter.newLine()
        }

        bufferedWriter.close()

        /*
        bufferedWriter.append("Test1\n")
        bufferedWriter.append("Test2")
        bufferedWriter.newLine()
        bufferedWriter.append("Test3\n")
        bufferedWriter.close()

         */


    }
}

=================================== ====================================

activity_main.xml 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>

That tutorial on using Apache Commons for reading CSV is written with the assumption that you are writing for JVM, not Android.关于使用 Apache Commons 读取 CSV 的教程是在假设您正在为 JVM 而不是 Android 编写的情况下编写的。 It's not simple to adapt it to Android.让它适应安卓并不简单。 I don't think the Apache Commons library is necessary anyway, because CSV is such a simple text-based format.我认为 Apache Commons 库无论如何都不是必需的,因为 CSV 是一种如此简单的基于文本的格式。

Here are a couple of simple extension functions that can be called on a File to either read a CSV as a 2D List of Strings, or write a 2D List of Strings to a File.这里有几个简单的扩展函数,可以在文件上调用它们来读取 CSV 作为二维字符串列表,或者将二维字符串列表写入文件。 Think of the 2D list as a List of lines of data.将二维列表视为数据行列表。 Each value in the inner List is all the values in that line.内部列表中的每个值都是该行中的所有值。

@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)
}

You should not do File IO operations on the main thread, because this freezes the UI and risks making your application crash with the Application Not Responding Error.您不应该在主线程上执行文件 IO 操作,因为这会冻结 UI 并有可能使您的应用程序因应用程序无响应错误而崩溃。 It looks like you have some kind of game loop so I'm not sure how to apply this advice in your case.看起来你有某种游戏循环,所以我不确定如何在你的情况下应用这个建议。

Here are alternate versions of the above functions that use FileInputStream and FileOutputStream so they are more versatile on Android (since you can't get direct File access for some storage locations):以下是使用 FileInputStream 和 FileOutputStream 的上述函数的替代版本,因此它们在 Android 上更加通用(因为您无法直接访问某些存储位置的文件):

@Throws(IOException::class)
fun FileInputStream.readAsCSV() : List<List<String>> {
    val splitLines = mutableListOf<List<String>>()
    reader().buffered().forEachLine {
        splitLines += it.split(", ")
    }
    return splitLines
}

@Throws(IOException::class)
fun FileOutputStream.writeAsCSV(values: List<List<String>>) {
    val csv = values.joinToString("\n") { line -> line.joinToString(", ") }
    writer().buffered().use { it.write(csv) }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM