ファイルの読み書き2


androidにファイルを格納できる場所には、内部ストレージ/外部ストレージがあります.
  • 内部リポジトリは、各アプリケーションが提供するリポジトリであり、アプリケーションを削除すると、一緒に削除されます.他のアプリケーションの内部リポジトリにアクセスできません.
  • 外部ストレージは、「パブリックスペース/アプリケーション専用スペース」に分けられます.ちょっと複雑なので、すぐにブログのリンクを見てください。
  • しかし、今はassetsフォルダのcsvファイルを読みたいだけです。

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            val am = resources.assets //resource Manager : Provides access to an application's raw asset files
            try {
                val inputStream = am.open("food_1.csv", AssetManager.ACCESS_BUFFER) 
                // accessMode를 이용해서 asset 읽기. 내용을 읽기 위해 inputStream 을 리턴 
                val br = BufferedReader((InputStreamReader(inputStream, Charset.forName("UTF-16"))))
                //리턴받은 InputStream(데이터가 전송되는 통로, 1byte 씩만 읽어옴. 한글 처리 x)의 byte를 "UTF-16"방식으로 처리 하겠다. - 한글 처리위해
                //괄호 안에서 처리한 inputstreamReader을 char 단위로 buffer을 이용해 읽겠다. - char로 처리 되어 있으므로 BufferdReader로 읽을 수 있음
                //(BufferdReader는 char 단위로 처리. BufferedInputStream은 byte 단위로처리)
    
                val list = br.use(BufferedReader::readLines)
                //br의 메소드인 readLines로 모든 라인을 읽어오자 
                //보다시피 한줄 한줄이 리스트 요소로 들어간다. 
                br.close()
                //stream을 닫고 memory leak 이 일어나지 않게 한다. 
            } catch (e: IOException) {
                e.printStackTrace();
            }
        }

    AssetManager.Open()メソッドのaccessMode


  • ACCESS BUFFER:高速・小読み取り(バッファ使用のためか?)
  • ACCESS RANDOM:ブロック単位で読み込みます.前後ナビゲーション
  • ACCESS STREAMING:順番に読み取る.時々前方探索
  • ACCESS UNKOWN:データへのアクセス方法が分からない場合、
  • これで、inputStreamを開き、ファイルを読み込み、inputStreamを閉じると、try-catch上で実行されます.
    1.ファイルを開いて正常に読み込みますが、Streamを閉じるときにエラーが発生しました
    2.ファイルが見つかりません
    3.ファイルが見つかりましたが読み込まれませんでした
    4.ファイルが見つからないためFileStreamを閉じようとしたが、ファイルを閉じることができなかった
    try-catchをそれぞれ処理します.

    内部/外部リポジトリのファイルの読み込み


    ソース

    注意:FileReaderはInputStreamReaderを継承します.したがって、inputStreamReaderのようにcharに基づいて読み取ります.-bufferReaderの使用
    byteで読み込む場合は、FileInputStream-BufferedInputStreamの使用

    ローカル(コンピュータ上)ファイルの読み込み

    
    fun main() {
        val br = BufferedReader(//char 단위로 처리.
            (InputStreamReader( //inputStream의 byte단위를 char단위로 변환시키는 중개자
                FileInputStream("파일이 있는 위치/파일이름.확장자"), //파일을 바이트 단위로 읽어서 inputStream 만듬
                Charset.forName("UTF-16")
            ))
        )
    
        //여기서 의문점이 생겼다.
        //FileInputStream(바이트 단위의 스트림)을 만들고 InputStreamReader로 byte >char 단위로 스트림을 변환하는
        //이중 처리를 하는 이유가 궁금했다.
        //FileReader를 이용하면 바로 char 단위로 파일을 읽는 inputStream을 만들 수 있는데 말이다.
        //하지만 직접 해보니..
        //FileReader는 인코딩을 지정할 수가 없다!(자바 11에서는 가능하다고함. 하지만 나는 1.8을 쓰고있지.)
        //그래서 굳이 이중처리를 해야함에도 불구하고,
        //FileInputStream로 바이트단위 but, 인코딩 지정가능 스트림 >> InputStreamReader로 char단위 스트림
        //이렇게 스트림을 만들어 주는 것 같다!!!
    
    //    val br = BufferedReader((FileReader("파일위치/파일이름.확장자")))
    
        val list = br.use(BufferedReader::readLines)
        br.close()
    
        list.forEach {
            println(it)
        }
    }

    ファイルをローカルに書き込み

    private fun writeCSV() {
            try {
                val map = mapOf("키" to "맵")
                val bw =
                    BufferedWriter(FileWriter(("파일위치/파일이름.확장자"), true))
                //fileWriter/BufferedWriter - char 단위로 파일 작성
                //append - true : 기존 파일 내용 냅두고 그 다음줄 부터 쓴다. false : 기존 파일 내용 날리고 덮어쓴다(새로쓴다)
                //바이트 단위로 파일을 쓰고싶다면 > FileOutputStream . BufferedOutputStream 이용
                val iterator = map.iterator()
                while (iterator.hasNext()) {
                    val word = iterator.next()
                    bw.write("${word.key},${word.value}")
                    bw.newLine()
                    bw.flush()
                    //버퍼의 내용을 파일에 write 한다.
                    //flush()를 호출하지 않는다면 내용이 버퍼에만 남고 파일에는 쓰이지 않는 상황이 됨.
                }
                bw.close()
                //close 호출은 스트림을 닫는 역할.
                // 스트림을 닫으면 그 스트림을 다시 이용하여 파일에 쓰는 것이 불가능
            } catch (e: Exception) {
                println(e)
            }
        }