본문 바로가기
전공 수업/모바일 프로그래밍(Android Studio)

[8주 차] - 안드로이드 파일 처리(Android File Processing)

by TwoJun 2023. 4. 23.

    과목명 : 모바일 프로그래밍(Mobile programming with Android Studio)

수업일자 : 2023년 04월 21일 (금)

Android Studio(Android Emulator)

 

 

 

 

 

1. 내장 메모리 파일 처리

1-1. 내장 메모리 파일 처리 

(1) 애플리케이션을 종료하고 다시 실행할 때, 사용한 곳에 이어서 작업하고 싶은 경우 내장 메모리 파일 처리를 이용합니다.

 

(2) 내장 메모리의 저장 위치 : / data / data / 패키지명 / files 디렉토리

 

 

 

 

1-2. 내장 메모리에서의 파일 처리 과정

- (1) → (2) → (3) 순서대로 진행

 

(1) openFileOutput() / openFileInput() 메소드로 파일 열기 

- FileOutputStream / FileInputStream 반환

 

(2) read() / write() 메소드로 파일 읽기, 쓰기

 

(3) close() 메소드로 파일 닫기

 

 

 

 

1-3. 파일 처리 기본 Code

(1) activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnWrite"
        android:text="내장 메모리에서 파일 쓰기"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnRead"
        android:text="내장 메모리에서 파일 읽기"/>

</LinearLayout>

 

 

(2) MainActivity.java

package com.example.fileprocessing;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnRead, btnWrite;
        btnRead = (Button) findViewById(R.id.btnRead);
        btnWrite = (Button) findViewById(R.id.btnWrite);

        btnWrite.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    FileOutputStream outFs = openFileOutput("file.txt", Context.MODE_PRIVATE);
                    String str = "파일 처리 테스트";
                    outFs.write(str.getBytes());
                    outFs.close();
                } catch (IOException e) { }
            }
        });

        btnRead.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    FileInputStream inFs = openFileInput("file.txt");
                    byte[] txt = new byte[30];
                    inFs.read(txt);
                    String str = new String(txt);
                    Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();
                    inFs.close();
                } catch (IOException e) {
                    Toast.makeText(getApplicationContext(), "파일 없음", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

 

<실행 결과>

- 애플리케이션 초기 구동 화면입니다.

MainActivity.java

- 버튼 클릭 시 파일 읽어오기가 가능합니다.

파일 읽기를 진행한 상태

 

 

 

 

 

 

2. 파일 처리 테스트 : 일기장 예제 Application Code

2-1. activity_main.xml

(1) 화면 디자인 및 편집하기

- DatePicker, EditText, Button 위젯을 각 1개씩 생성합니다.

 

- 각 위젯의 아이디 속성은 datePicker1, edtDiary, btnWrite으로 부여합니다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <DatePicker
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:datePickerMode="spinner"
        android:id="@+id/datePicker1"
        android:calendarViewShown="false" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:id="@+id/edtDiary"
        android:background="#0000ff"
        android:lines="8"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:enabled="false"
        android:id="@+id/btnWrite"
        android:text="Button"/>

</LinearLayout>

 

<위젯 배치 결과>

각 위젯 배치 결과

 

 

 

 

2-2. MainActivity.java

(1) activity_main.xml 파일에 존재하는 3개 위젯에 대응하는 위젯 변수 3개를 선언합니다.

 

(2) 파일 이름을 지정할 문자열 변수를 선언합니다.

- 파일 이름은 "연_월_일.txt" 형식으로 지정

 

(3) 위젯 변수에 activity_main.xml의 위젯을 대입합니다.

 

(4) Calendar 클래스를 사용해 현재 날짜의 연/월/일을 구한 후 DatePicker를 초기화합니다.

 

(5) DatePicker의 날짜가 변경되면 변경된 날짜에 해당하는 일기 파일(연_월_일.txt) 내용을 EditText 부분에 출력합니다.

 

(6) 현재 날짜 파일(연_월_일.txt)을 읽어들여 일기 내용을 반환하는 readDiary() 메소드를 구현합니다.

 

(7) 맨 아래 버튼을 클릭했을 때, 동작하는 내용을 onCreate() 메인 메소드 내부에 구현합니다.

package com.example.a8weekssimplediary2;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Toast;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;

public class MainActivity extends AppCompatActivity {
    DatePicker dp;
    EditText edtDiary;
    Button btnWrite;
    String fileName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("Simple Diary");

        dp = (DatePicker) findViewById(R.id.datePicker1);
        edtDiary = (EditText) findViewById(R.id.edtDiary);
        btnWrite = (Button) findViewById(R.id.btnWrite);

        Calendar cal  = Calendar.getInstance();
        int cYear = cal.get(Calendar.YEAR);
        int cMonth = cal.get(Calendar.MONTH);
        int cDay = cal.get(Calendar.DAY_OF_MONTH);

        dp.init(cYear, cMonth, cDay, new DatePicker.OnDateChangedListener() {
            public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                fileName = Integer.toString(year) + "_"
                        + Integer.toString(monthOfYear + 1) + "_"
                        + Integer.toString(dayOfMonth + 1) + ".txt";
                String str = readDiary(fileName);
                edtDiary.setText(str);
                btnWrite.setEnabled(true);
            }

            String readDiary(String fName) {
                String diaryStr = null;
                FileInputStream inFs;
                try {
                    inFs = openFileInput(fName);
                    byte[] txt = new byte[500];
                    inFs.read(txt);
                    inFs.close();
                    diaryStr = (new String(txt)).trim();
                    btnWrite.setText("수정하기");
                } catch (IOException e) {
                    edtDiary.setHint("일기 없음");
                    btnWrite.setText("새로 저장");
                }
                return diaryStr;
            }
        });

        btnWrite.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    FileOutputStream outFs = openFileOutput(fileName, Context.MODE_PRIVATE);
                    String str = edtDiary.getText().toString();
                    outFs.write(str.getBytes());
                    outFs.close();;
                    Toast.makeText(getApplicationContext(), fileName +" 이 저장됨", Toast.LENGTH_SHORT).show();
                } catch (IOException e) {}
            }
        });
    }
}

 

<실행 결과>

- 애플리케이션 초기 실행 화면입니다

- 애플리케이션 실행 시점 2023년 4월 22일을 기준으로 작성된 내용이 없으므로 EditText 영역이 공백입니다.

MainActivity.java - 초기 실행 화면

 

- 2023년 4월 21일에 내용을 작성했기 때문에 날짜를 바꿔보면 EditText 영역에 읽어들여진 텍스트가 출력됩니다.

- 해당 일자의 일기가 존재하기 때문에 맨 하단 버튼이 "수정하기"로 변경되었습니다.

2023-04-21 일자에 저장된 일기가 출력된다.

 

- 선택한 날짜에 일기가 없다면 EditText 영역에 "일기 없음" 문구가 노출되고 맨 하단의 버튼이 "새로 저장"으로 변경됩니다.

일기가 없는 것을 확인할 수 있다.

 

- 현재 금일 기준으로 일기가 없으므로 새로운 내용을 쓰고 내용을 저장할 수 있습니다.

새로운 내용을 작성하고 저장을 완료한다.

 

 

 

 

 

 

3. 파일 처리 기본 : 내장 메모리 파일 처리

3-1. 일기장 Application에 대한 저장된 텍스트 파일 확인해 보기

(1) Android Studio 최상단 메뉴 View → Tool Windows Device File Explorer 메뉴를 클릭합니다.

Device File Explorer를 클릭

 

 

(2) Android Studio에서 제공하는 DDMS Tool을 사용하여 쓰여진 텍스트 파일을 확인합니다.

- 확인 경로 : / data / data / 프로젝트의 패키지명 / files

저장된 텍스트 파일을 해당 경로에서 확인할 수 있다.

 

 

(3) 파일들을 Local 환경으로 가져올 수 있으며 마우스 오른쪽 버튼을 클릭해 "Save As..." 메뉴를 통해 저장할 로컬 디렉토리를 설정할 수 있습니다.

로컬로 파일을 가져올 수 있다.

 

 

 

 

 

 

4. raw 디렉토리 파일 처리

4-1. raw 디렉토리 파일 처리

(1) 프로젝트의 / res / raw 디렉토리에 필요한 파일을 저장해서 사용합니다.

 

(2) openRawResource() 메소드를 사용해서 접근(InputStream 클래스 사용)합니다.

 

(3) / res / raw 디렉토리는 프로젝트에 포함된 디렉토리이므로 읽기 전용만 사용 가능합니다.

 

 

 

 

4-2. raw 디렉토리 파일 읽기 예제 Code

(1) activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btnRead"
        android:text="/res/raw에서 파일 읽기"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/edtRaw"
        android:lines="10"/>
</LinearLayout>

 

<위젯 배치 결과>

위젯 배치 결과

 

(2) raw 디렉토리 생성

- 프로젝트 디렉토리 경로에서 res 디렉토리 기준 마우스 우측 클릭

- New → Android Resource Directory → Resource type raw, Directory name까지 raw로 설정합니다.

Android Resource Directory 클릭

 

Android Resource Directory

 

(3) 생성된 raw 디렉토리에 raw_test.txt 파일을 생성하고 읽어들일 텍스트를 별도로 입력합니다.

raw_test.txt

 

(4) MainActivity.java

package com.example.a8weekssimplediary;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;

import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btnRead;
        final EditText edtRaw;
        btnRead = (Button) findViewById(R.id.btnRead);
        edtRaw = (EditText) findViewById(R.id.edtRaw);

        btnRead.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    InputStream inputS = getResources().openRawResource(R.raw.raw_test);
                    byte[] txt = new byte[inputS.available()];
                    inputS.read(txt);
                    edtRaw.setText(new String(txt));
                    inputS.close();
                } catch (IOException e) {}
            }
        });
    }
}

 

<실행 결과>

- 애플리케이션 초기 구동 화면입니다.

MainActivity.java - 초기 구동 화면

 

- 파일 읽기 버튼을 통해 저장된 파일을 아래와 같이 불러올 수 있게 됩니다.

MainActivity.java - 파일 읽어오기

 

 

 

 

 

 

5. Etc

5-1. 안드로이드 파일 처리 (1) 

(1) 내장 메모리의 파일 저장 위치는 / data / data / 패키지명 / files이다.

 

(2) 읽기 전용 파일의 경우 프로젝트의  / res / raw 디렉토리를 사용할 수 있다.

 

(3) 외장 메모리 카드(SD카드)에 저장하는 외부 저장소 이름은 sdcard이다.

 

 

 

 

5-2. 안드로이드의 대화 상자(Dialog)

(1) 안드로이드에서 대화 상자(Dialog)에서 <OK> 버튼은 setPositiveButton, <Cancel> 버튼은 setNegativeButton, 라디오 버튼(RadioButton) 목록 출력은 setSingleChoiceItems, 체크박스(CheckBox) 목록 출력은 setMultiChoiceItems를 사용합니다.

 

 

 

 

5-3. 안드로이드 파일 처리 (2)

(1) 내장 메모리에서 파일을 읽거나 쓰는 일반적인 절차는 다음과 같습니다.

- 파일을 읽기 위해 openFileInput() 메소드를 사용하는데 이 메소드는 FileInputStream을 반환합니다.

 

- 파일을 쓰기 위해 openFileOutput() 메소드를 사용하면 FileOutputStream을 반환합니다.

 

- Java에서 제공하는 파일을 읽거나 쓰는 java.io.FileInputStream 클래스와 java.io.FileOutputStream의 read(), write() 메소드를 사용하여 파일을 처리합니다.

 

 

 

 

5-4. raw 디렉토리 처리

(1) 다음은 / res / raw 디렉토리의 mytext.txt를 읽는 Java 코드입니다. 

InputStream inputS = getResources().openRawResource.(R.raw.mytext);

byte[] txt = new byte[inputS.available()];

inputS.read(txt);

InputStream inputS = getResources().openRawResource(R.raw.mytext);
byte[] txt = new byte[inputS.available()];
inputS.read(txt);

 

 

 

 

 

 

6. Reference

(1) Reference

- Android Studio를 활용한 안드로이드 프로그래밍 / 한빛아카데미(Hanbit Academy, Inc.)

 

(2) URL

https://www.hanbit.co.kr/store/books/look.php?p_code=B1212492850 

 

IT CookBook, Android Studio를 활용한 안드로이드 프로그래밍(7판)

안드로이드 프로그래밍을 하면서 부딪힐 수 있는 다양한 오류나 실수까지 친절하게 안내하여 시행착오 없이 안드로이드를 빠르게 정복할 수 있습니다.

www.hanbit.co.kr

 

 

 

- 학부에서 수강했던 전공 수업 내용을 정리하는 포스팅입니다.

- 내용 중에서 오타 또는 잘못된 내용이 있을 시 지적해 주시기 바랍니다.

댓글