본문 바로가기
개발/Android

[Android] OpenCSV로 안드로이드에서 csv 파일 읽고 쓰기

by JhDroid 2021. 1. 8.
728x90

OpenCSV

  • 자바로 CSV 파일을 읽거나 쓸 때 사용할 수 있는 라이브러리입니다.
  • 간단한 CSV 파일 생성 및 쓰고 읽는 방법을 가이드합니다.
  • github : github.com/JhDroid/android-opencsv-sample
 

JhDroid/android-opencsv-sample

OpenCSV Sample Project. Contribute to JhDroid/android-opencsv-sample development by creating an account on GitHub.

github.com

  • 가이드 코드와 github 코드가 조금 다를 수 있습니다.
  • 가이드는 코틀린 코드로 작성했습니다.
  • github 샘플 프로젝트에 자바 코드도 있습니다!(클래스명 앞에 '_' 붙어있는 파일이 자바 코드입니다)
    • 21.02.23 수정 : java 패키지 안에 있는 클래스는 자바 코드로 작성되었습니다. (Java...)

 

OpenCSV 데이터 쓰고 저장하기(내부 저장소)

  • 의존성 추가
implementation 'com.opencsv:opencsv:4.4'

 

  • CSVWriter의 writeAll()을 이용한 데이터 쓰기
//파일 경로를 무조건 넘겨받기 위해 생성자에 추가
class CsvHelper(private val filePath: String) {
    fun writeAllData(fileName: String, dataList: ArrayList<Array<String>>) {
        try {
            FileWriter(File("$filePath/$fileName")).use { fw ->
                //writeAll()을 이용한 리스트 데이터 등록
                CSVWriter(fw).use {
                    it.writeAll(dataList)
                }
            }
        } catch (e: IOException) {
            if (BuildConfig.DEBUG) {
                e.printStackTrace()
            }
        }
    }
}

 

  • CSVWriter의 writeNext()를 이용한 데이터 쓰기
//파일 경로를 무조건 넘겨받기 위해 생성자에 추가
class CsvHelper(private val filePath: String) {
     fun writeData(fileName: String, dataList: ArrayList<Array<String>>) {
        try {
            FileWriter(File("$filePath/$fileName")).use { fw ->
                //writeNext()를 이용한 리스트 데이터 등록
                CSVWriter(fw).use {
                    for (data in dataList) {
                        it.writeNext(data)
                    }
                }
            }
        } catch (e: IOException) {
            if (BuildConfig.DEBUG) {
                e.printStackTrace()
            }
        }
    }
}

 

  • 테스트용 데이터 추가
class MainActivity : AppCompatActivity() {
    //테스트용 파일명1
    private val FILE_NAME_1 = "jhdroid_sample_1.csv"

    //테스트용 파일명2
    private val FILE_NAME_2 = "jhdroid_sample_2.csv"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //내부 저장소 경로
        val filePath = filesDir.toString()

        val csvHelper = CsvHelper(filePath)

        //테스트용 데이터 리스트1
        val dataList1 = arrayListOf<Array<String>>()

        //헤더로 사용할 데이터 추가
        dataList1.add(arrayOf("Name", "Age"))

        //데이터 추가
        dataList1.add(arrayOf("Kim", "28"))
        dataList1.add(arrayOf("Lee", "22"))
        dataList1.add(arrayOf("Kawk", "25"))

        csvHelper.writeAllData(FILE_NAME_1, dataList1)

        //테스트용 데이터 리스트2
        val dataList2 : ArrayList<Array<String>> = arrayListOf()

        //헤더로 사용할 데이터 추가
        dataList2.add(arrayOf("Name", "Age"))

        //데이터 추가
        dataList2.add(arrayOf("Jo", "19"))
        dataList2.add(arrayOf("Jung", "30"))
        dataList2.add(arrayOf("Heo", "24"))

        csvHelper.writeData(FILE_NAME_2, dataList2)
    }
}
  • csv 파일을 내부 저장소에 저장하도록 했습니다, 경로는 '/data/data/<PackageName>/files' 입니다.

 

  • 저장된 파일 확인하는 방법(Device File Explorer) (더보기를 선택하면 내용이 표시됩니다.)
더보기
  • 저장된 파일을 쉽게 확인하는 방법은 안드로이드 스튜디오의 Device File Explorer를 사용하면 됩니다.
  • 스튜디오 오른쪽 하단에 Device File Explorer를 선택

 

  • 내부 저장소 경로로 이동 후 패키지명 검색 (/data/data/<PackageName>/files)
    • 패키지명 검색은 Device File Explorer에서 아무 파일이나 누른 후 패키지명을 입력하면 됩니다.

 

  • 만약 파일이 없다면 최신화가 안된 것이니 아무 파일이나 우클릭 - Synchronize 선택

 

  • 생성된 파일 선택 후 우클릭 - Save As 선택하거나 선택 후 ctrl + shift + s로 다른 이름으로 저장

 

  • 파일 확인

  • writeAll(), writeNext() 두 방법 모두 데이터가 정상적으로 들어간 것을 확인할 수 있습니다.

 

CSV 파일 읽기

  • CSVReader의 readAll()을 이용한 데이터 읽기
    • readAll()을 사용하면 csv 파일 내의 데이터를 List<Array<String>>(자바 : List<String[]>)으로 리턴 받습니다.
class CsvHelper(private val filePath: String) {
    fun readAllCsvData(fileName: String) : List<Array<String>> {
       return try {
            FileReader("$filePath/$fileName").use { fr ->
                //readAll()을 이용해 데이터 읽기
                CSVReader(fr).use {
                    it.readAll()
                }
            }
        } catch (e: IOException) {
            if (BuildConfig.DEBUG) {
                e.printStackTrace()
            }

            listOf()
        }
    }
}
//MainActivity - onCreate()
val filePath = filesDir.toString()

val csvHelper = CsvHelper(filePath)

//1번 파일 읽기
var dataList = csvHelper.readAllCsvData(FILE_NAME_1)
for (data in dataList) {
    Log.d("jhdroid_test", "data : ${Arrays.deepToString(data)}")
}
2021-01-08 16:03:23.500 27822-27822/com.jhdroid.opencsv.sample D/jhdroid_test: data : [Name, Age]
2021-01-08 16:03:23.501 27822-27822/com.jhdroid.opencsv.sample D/jhdroid_test: data : [Kim, 28]
2021-01-08 16:03:23.501 27822-27822/com.jhdroid.opencsv.sample D/jhdroid_test: data : [Lee, 22]
2021-01-08 16:03:23.501 27822-27822/com.jhdroid.opencsv.sample D/jhdroid_test: data : [Kawk, 25]

 

  • for문을 이용한 데이터 읽기
    • readNext() 함수가 있으나 for문을 이용하는 방법이 더 간결해서 변경했습니다.
class CsvHelper(private val filePath: String) {
    fun readCsvData(fileName: String) : List<Array<String>> {
        return try {
            FileReader("$filePath/$fileName").use { fr ->
                val dataList = arrayListOf<Array<String>>()

                //for문을 이용해 데이터 읽기
                CSVReader(fr).use {
                    for (data in it) {
                        dataList.add(data)
                    }
                }

                dataList
            }
        } catch (e: IOException) {
            if (BuildConfig.DEBUG) {
                e.printStackTrace()
            }

            listOf()
        }
    }
}
//MainActivity - onCreate()
val filePath = filesDir.toString()

val csvHelper = CsvHelper(filePath)

//2번 파일 읽기
val dataList = csvHelper.readCsvData(FILE_NAME_2)
for (data in dataList) {
    Log.d("jhdroid_test", "data : ${Arrays.deepToString(data)}")
}
2021-01-08 16:03:23.501 27822-27822/com.jhdroid.opencsv.sample D/jhdroid_test: data : [Name, Age]
2021-01-08 16:03:23.501 27822-27822/com.jhdroid.opencsv.sample D/jhdroid_test: data : [Jo, 19]
2021-01-08 16:03:23.501 27822-27822/com.jhdroid.opencsv.sample D/jhdroid_test: data : [Jung, 30]
2021-01-08 16:03:23.501 27822-27822/com.jhdroid.opencsv.sample D/jhdroid_test: data : [Heo, 24]
  • 두 방법 모두 데이터를 정상적으로 읽어올 수 있는 것을 확인할 수 있습니다.

 

* 글에 틀린 부분이 있으면 댓글 부탁드립니다 :D

728x90