본문 바로가기
Android App/Kotlin

파일 입출력-내부 저장소 사용(실제 데이터 사용, 입/출력 스트림)

by AppJinny 2022. 11. 18.

*파일 입출력-내부 저장소 파일 읽기, 쓰기

-파일 활용 시 텍스트 파일의 여부와 파일 읽고 쓸 때 사용하는 API가 달라지므로 먼저 파일의 형태를 알아야 함

-파일의 기본 정보 사용 : File() 클래스 생성하여 메서드 사용

-파일의 실제 데이터 읽고 쓰기 : 스트림 사용(읽기전용 스트림, 쓰기전용 스트림)

 

*파일 입출력-내부 저장소 사용(실제 데이터 사용, 입/출력 스트림)

-파일의 기본정보는 File클래스를 사용해 간단하게 처리가능

-파일의 실제 데이터를 읽고 쓰기 위해서는 스트림 클래스 사용

-스트림은 파일에 파이프를 하나 연결해 놓고 파이프를 통해 데이터를 꺼내오는 방식으로 동작

-파이프는 파일을 읽거나 쓸 때 연결하고 사용이 끝나면 제거(.close())하는 방식으로 효율적 사용

-읽기전용 스트림, 쓰기전용 스트림으로 구분해 사용

 

*스트림(stream) 종류

-크게 입력 스트림과 출력 스트림으로 구분

--입력 스트림 : 파일을 읽어서 가져오는 스트림

--출력 스트림 : 파일을 쓰는 스트림

-입/출력 스트림으로 구분한 뒤 파일 종류에 따라 스트림이 나뉨(국가, 언어, 컴퓨터 기종별 사용하는 방식이 다르기 때문에)

-바이너리(Byte)파일 에 사용하는 스트림과 일반텍스트(Charater)에 사용하는 스트림으로 나뉨

--바이너리(Byte) 스트림 :입력(Input), 출력(Output) 계열 , 그림, MP3 등에 사용

--일반텍스트(Charater) 스트림 : 읽기(Reader), 쓰기(Writer) 계열

스트림의 종류

 

*내부 저장소 사용 - 텍스트 파일 읽기와 쓰기

-읽기 : Reader계열의 스트림 사용 

-파일 경로를 파라미터로 전달 받아 파일 정보를 읽은 후 스트림을 사용하여 파일의 실제 데이터를 읽음

-쓰기 : Writer계열의 스트림 사용

-총 3개의 파라미터(디렉터리, 파일명, 작성할내용)를 사용해 새로운 텍스트파일 생성

 

-MainActivity.kt

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

        //1
        //Reader 계열의 스트림을 사용하여 파일 데이터 읽기
        //파일 경로를 파라미터로 전달받아 파일정보를 읽은 후 스트림을 사용하여 파일의 실제 데이터 읽기

        //1-1
        //app - java디렉터리 밑 패키지명 우클릭 - New - Kotlin Class/File
        //FileUtil.kt 클래스 생성하여 코드 작성

        //1-2
        //FileUtil.kt 클래스에 생성한 파일 데이터를 읽어오는 메서드 readTextFile(경로) 사용하기
        //내부 저장소 파일을 읽을 때 내부저장소인 filesDir과 파일명 조합으로 경로 지정
        //디렉터리와 파일명 사이를 슬래시(/)로 구분
        var read = FileUtil()
        val content = read.readTextFile("${filesDir}/파일명.txt")

        //1-3
        //지정한 경로에 있는 텍스트파일 데이터를 읽어온 변수 content의 내용확인
        //Log.d("read","$content")

        //2
        //Writer 계열의 스트림을 사용하여 파일 데이터 쓰기
        //FileUtil.kt 클래스에 writeTextFile()메서드 생성

        //2-1
        //내부 저장소 파일에 텍스트 파일 쓰기
        //writeTextFile() 메서드 파라미터 3개 : 생성할 디렉터리명, 파일명, 쓸 내용
        //var write = FileUtil()
        //write.writeTextFile("newDir", "newFilename.txt", "글의 내용")



        //3
        //내부저장소 텍스트 파일 읽고 쓰는 코드 축약 ****************
        //안드로이드는 파일을 읽거나 쓸 때 스트림으로 반환해주는 메서드를 제공함
        //이 메서드들을 조합하면 앞서 만든 1,2번의 코드를 작성하지 않고
        //짧은 코드로 내부저장소의 텍스트파일을 읽고 쓸 수 있음

        //openFileInput() : 파일을 읽어서 스트림으로 반환해주는 메서드
        //openFileOutput() : 스트림으로 파일을 쓰는 메서드

        //3-1
        //파일 읽기 openFileInput()
        //파일을 읽어서 저장할 변수(readContent)선언
        var readContent = ""
        //lines에는 줄 단위의 텍스트가 저장됨
        //joinToString() 메스드로 줄마다 새줄 \n 추가 후 사용가능
//        openFileInput("파일경로").bufferedReader().useLines { lines ->
//            readContent = lines.joinToString("\n")
//        }

        //3-2
        //파일 쓰기 openFileOutput()
        //파일내용을 담을 변수(writeContent) 선언
        val writeContent = "Hello\nworld!!"
        //Context.MODE_PRIVATE : 기존 동일한 파일명 있을 시 덮어쓰기
        //Context.MODE_PRIVATE 대신에 Context.MODE_APPEND를 사용하면
        //기존에 동일한 파일명이 있을 경우 기존 내용에 이어서 새로운 내용 저장 가능
//        openFileOutput("파일명", Context.MODE_PRIVATE).use { stream ->
//            //내용이 담긴 변수(writeContent)는 스트림에 쓸 때 바이트 배열로 변환해야 함(toByteArray())
//            stream.write(writeContent.toByteArray())
//        }

    }//onCreate
}//MainActivity

 

-FileUtil

class FileUtil {

    //1
    //Reader 계열의 스트림을 사용하여 파일 데이터 읽기

    //1-1
    //파라미터(fullPath)로 파일의 경로를 전달받는 메서드 생성(는)
    fun readTextFile(fullPath: String): String{

        //1-2
        //먼저 파라미터로 전달된 변수 fullPath 의 경로를 File()클래스에 넣어 파일정보를 생성하고
        //실제 경로안에 파일이 있는지 검사(exsits())
        val file = File(fullPath)
        //만약 파일경로 안에 파일이 없다면(!) 공백 값 리턴
        if (!file.exists()) return ""

        //1-3
        //스트림 파이프 생성!
        //FileReader()메서드로 파일(변수 file)을 읽어 변수(reader)에 저장하고
        //BufferedReader()에 담아 속도 향상시켜 변수(buffer)에 저장
        val reader = FileReader(file)
        val buffer = BufferedReader(reader)

        //1-4
        //한 줄씩 읽은 내용을 임시저장할 변수(temp)를 먼저 선언하고
        //모든내용을 저장하는 StringBuffer()클래스를 생성한 변수(result)선언
        var temp = ""
        val result = StringBuffer()

        //1-5
        //while 반복문을 사용해 파일의 데이터를 한줄씩 읽어 모든내용을 저장하는 코드 작성
        while (true){

            //1-6
            //파일을 읽고 속도향상까지 시켜 저장했던 파일의 데이터를 읽어서 가지고 있는
            //변수 buffer에서 데이터 한 줄을 꺼내 읽고(readLine()) 임시저장할 변수(temp)에 저장
            temp = buffer.readLine()

            //1-7
            //if 조건문을 사용해 그 값(temp)이 null이라면 더이상 읽을 데이터가 없는 뜻이므로 반복문을 빠져나가고
            //값이 있다면(null이 아니라면) 모든내용을 저장하는 클래스를 가진 result변수에 buffer를 저장 append()함
            if (temp == null) break
            else result.append(buffer)

        }

        //1-8
        //스트림 파이프 제거!
        //buffer를 닫고(close()) 결과값을 문자열로 리턴
        buffer.close()
        return result.toString()

    }//readTextFile

    //2
    //Writer 계열의 스트림을 사용하여 파일 데이터 쓰기
    //쓰기파일은 총3개의 파라미터를 사용(파일생성할 디렉터리, 파일명, 작성할내용)

    //2-1
    //3개의 파라미터를 가진 메서드(writeTextFile()) 생성
    fun writeTextFile(directory: String, filename: String, content: String){

        //2-2
        //디렉터리에 생성할 디렉터리 이름인 directory가 존재하는지 검사하고 없으면 생성
        //파일 기본 정보를 사용하는 File()클래스를 생성하여 사용
        val dir = File(directory)
        if (!dir.exists()) {
            //만약 directory이름의 파일이 존재하지 않는다면
            //디렉터리 생성 mkdirs()
            dir.mkdirs()
        }

        //2-3
        //생성된 디렉터리(directory)에 파일명(filename)을 합해
        //FileWriter 파라미터로 생성하여 변수(writer)에 저장
        //쓰기속도 향상을 위해 BufferedWriter()하여 변수(buffer)에 저장
        val writer = FileWriter("$directory/$filename")
        val buffer = BufferedWriter(writer)

        //2-4
        //변수 buffer로 내용을 쓰고 닫기 close()
        buffer.write(content)
        buffer.close()

    }//writeTextFile


}//FileUtil

 

*****MainActivity.kt 의 코드 작성 순서 번호 3번 

-내부저장소의 텍스트 파일을 읽고 쓸 때 코드를 축약해서 사용하는 메서드가 있음

-안드로이드는 파일을 읽거나 쓸 때 스트림으로 반환해주는 메서드를 제공함

-openFileInput() : 파일을 읽어서 스트림으로 반환해주는 메서드

-openFileOutput() : 스트림으로 파일을 쓰는 메서드

 

 

 

*API(Application Programming Interface) : 응용 프로그래밍 인터페이스

-API 는 다른 사람이 쓴 코드를 말하는 라이브러리와, 라이브러리를 사용하는데 필요한 설명서, 설계도를 포함한 것

-API 사용 : 사용설명서인 api 문서를 읽으면서 사용함. api 마다 사용하는 방법이 다 다름

-Android 의 API 사용 : gradle의 dependency 에 사용하려는 라이브러리를 추가해주는 식으로 사용

-gradle : 빌드 자동화도구, 안드로이드 스튜디오에서 앱을 빌드할때 내가 사용하려는 라이브러리를 자동으로 빌드해주는 도구

-참고 : https://salix97.tistory.com/122