주니어개발자_ฅʕ•̫͡•ʔฅ

Andriod 외부저장소 파일 입출력 (JSON파일 만들기, JAVA) 본문

AndroidStudio

Andriod 외부저장소 파일 입출력 (JSON파일 만들기, JAVA)

뚜비뚜밥_98 2021. 9. 28. 22:10

Android Studio를 이용한 파일 입출력

(마지막에 전체 소스코드 첨부)

참고 사이트

 

android에서 저장소는 내부저장소외부저장소로 나뉘는데

간단하게 설명하자면

 

내부저장소

내부저장소를 사용하는 앱에서만 접근 가능, 다른 앱에선 접근 불가

이 말은 내부저장소를 사용하는 앱에서 저장한 데이터는

다른 앱에서 사용할 수 없다는 것이다.

 

내부저장소는 앱 자체에 있는 저장소를 사용하다보니

해당 앱을 삭제하면 저장소에 저장된 데이터도 함께 사라진다

 

 

외부저장소

다른 앱에서도 접근 가능

데이터를 저장한 앱이 아닌 다른 앱들도

저장소에 접근하여 데이터 사용이 가능하다.

 

외부저장소에 저장된 데이터는 앱을 삭제해도 지워지지 않는다.

 

.

.

.

 

오늘은 외부저장소에 폴더 및 파일을 생성하여

데이터를 입력하고

입력한 데이터를 읽어 올 것이다.

 

오늘 구현할 앱 실행 방법

문자열 입력 → 입력 버튼 클릭 → 외부저장소에 문자열 저장

읽기 버튼 클릭 → 저장한 데이터 읽어오기

왼쪽과 같이 텍스트 입력 후 '입력'버튼을 누르면 오른쪽과 같은 화면이 됨

 

JSON을 이용한 파일 입출력에는

대부분 두가지 방식으로 나뉘던데

(인터넷 찾다가 많이 본 케이스 2가지)

 

1

lib에 json-simple-1.1.1.jar파일을 추가하여

gradle에 추가한 후

import org.json.simple.JSONObject;

를 사용한 경우와

 

2

위와 같은 과정 없이 그냥 있는대로

import org.json.JSONObject;

를 사용한 경우

 

물론 본인은 두가지 경우 다 해봤다

 

오늘 사용할 방법은 2번

그래서 jar 파일을 추가하는 부분이 없다.

 

 

먼저 Mainfest에 저장소의 데이터를

읽기 및 쓰기를 위한 퍼미션을 추가해준다.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

 

퍼미션을 추가했다면 MainActivity로 넘어가서

onCreate 메소드 안에

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MODE_PRIVATE);

 

위와 같이 권한 설정을 작성해준다.

 

그리고 외부메모리 상태 확인을 위한 메서드 작성

 /**
     * 외부메모리 상태 확인 메서드
     */
    boolean checkExternalStorage() {
        String state = Environment.getExternalStorageState();
        // 외부메모리 상태
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // 읽기 쓰기 모두 가능
            Log.d("STATE", "외부메모리 읽기 쓰기 모두 가능");
            Toast.makeText(getApplicationContext(),"외부메모리 읽기 쓰기 모두 가능",Toast.LENGTH_SHORT).show();
            return true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){
            //읽기전용
            Log.d("STATE", "외부메모리 읽기만 가능");
            Toast.makeText(getApplicationContext(),"외부메모리 읽기만 가능",Toast.LENGTH_SHORT).show();
            return false;
        } else {
            // 읽기쓰기 모두 안됨
            Log.d("STATE", "외부메모리 읽기쓰기 모두 안됨 : "+ state);
            Toast.makeText(getApplicationContext(),"외부메모리 읽기쓰기 모두 안됨 : "+ state,Toast.LENGTH_SHORT).show();
            return false;
        }
    }

 

다시 onCreate 메서드로 돌아와서

checkExternalStorage(); //외부메모리 상태 확인 메서드 호출

작성

 

입력값 문자열을 JSONObject로 만든 후 JSONArray에 저장 메소드

(JSONObject to JSONArray)

    public JSONArray insertData(String id, String content){
        COUNT++; //입력한 데이터가 몇개인지 카운트하는 변수, 없어도 무관

        try {

            JSONObject sObject = new JSONObject();//배열 내에 들어갈 json
 			JSONArray jArray = new JSONArray();
            
			//COUNT변수 정수형에서 문자형으로 변환 후 JSONObject에 입력
            sObject.put("num",Integer.toString(COUNT));
            sObject.put("id", id);
            sObject.put("content", content);

			//JSONObject to JSONArray
            return jArray.put(sObject); 

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

 

버튼 눌렀을때 저장된 JSONArray를 JSONObject로 변환( onCreat 메소드에서 작성)

(JSONArray to JSONObject)

(json을 배열로 변환하지 않고 저장해도 됨)

(그러나 본인은 다음에 데이터를 다시 사용해야 하기 때문에 배열로 정리)

  //파일에 쓰기 버튼
        writeBtn.setOnClickListener(view->{

            JSONArray jArray = insertData(idText.getText().toString(),contentText.getText().toString());

            try {
                obj.put("item", jArray);//배열 넣음
                writeFile(obj);
                
                Toast.makeText(getApplicationContext(),"입력완료",Toast.LENGTH_SHORT).show();
            } catch (JSONException e) {
                e.printStackTrace();
            }

            idText.setText("");
            contentText.setText("");
        });

 

json 파일 생성 및 입력 메소드

public void writeFile(JSONObject object) {
        String fileTitle = "test.json";
        
        //저장소 위치 -> "/storage/self/peimary/test.json"
        File file = new File(Environment.getExternalStorageDirectory(), fileTitle);
        
        // new File( "/storage/self/peimary/",fileTitle);
        //위와 같이 저장소를 직접 입력해도 작동된다.

        try {
        
          /**
            * 폴더 생성
            * File dir = new File(Environment.getExternalStorageDirectory(), "Data");
            * if (!dir.exists()){
            * dir.mkdir();
            * }
            **/
            
            
            //파일이 존재하지 않다면 생성
            if (!file.exists()) {
                file.createNewFile();
            }
        
        // FileWriter을 사용해도 상관 없음
        // 그러나 본인은 이어쓰기에 용이한 BufferedWriter 사용
            BufferedWriter bw = new BufferedWriter(new FileWriter(file,true));
            bw.write(object.toString());
            
            bw.newLine();
            bw.close();
            
        } catch (IOException e) {
            Log.i("저장오류",e.getMessage());
        }
    }

 

json 형식으로 저장된 데이터 파일 읽어오는 메소드

  public void readFile() {

        String fileTitle = "test.json";
        File file = new File(Environment.getExternalStorageDirectory(), fileTitle);

        try {
            BufferedReader reader = new BufferedReader(new FileReader(file));
            String result = "";
            String line;

            while ((line = reader.readLine()) != null) {
                result += line;
            }
            tv.setText(result);
            reader.close();

        } catch (FileNotFoundException e1) {
            Log.i("파일못찾음",e1.getMessage());
        } catch (IOException e2) {
            Log.i("읽기오류",e2.getMessage());
        }

    }

 

전체 MainActivity.class 소스코드

 

import android.Manifest;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;


import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;


public class MainActivity extends AppCompatActivity {

    private Button readBtn,writeBtn;
    private EditText idText, contentText;


    private int COUNT = 0;
    private JSONObject obj = null;
    private TextView tv; //저장한 json값 불러오기기

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

        writeBtn = (Button) findViewById(R.id.writeBtn);
        readBtn = (Button) findViewById(R.id.readBtn);
        idText = (EditText)findViewById(R.id.idText);
        contentText = (EditText)findViewById(R.id.contentText);

        tv = (TextView) findViewById(R.id.tv);

        obj = new JSONObject();

        /** 외부 저장소에에 저장하기 위 권한 설정 **/
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MODE_PRIVATE);
        checkExternalStorage();

        //파일에서 읽어오기기
       readBtn.setOnClickListener(view->{
            readFile();
        });

       //파일에 쓰기
        writeBtn.setOnClickListener(view->{

            JSONArray jArray = insertData(idText.getText().toString(),contentText.getText().toString());

            try {
                obj.put("item", jArray);//배열을 넣음
                writeFile(obj);
                Toast.makeText(getApplicationContext(),"입력완료",Toast.LENGTH_SHORT).show();
            } catch (JSONException e) {
                e.printStackTrace();
            }

            idText.setText("");
            contentText.setText("");
        });
    }
    
    public JSONArray insertData(String id, String content){
        COUNT++; //입력한 데이터가 몇개인지 카운트하는 변수, 없어도 무관

        try {

            JSONObject sObject = new JSONObject();//배열 내에 들어갈 json
			JSONArray jArray = new JSONArray();
            
            //COUNT변수 정수형에서 문자형으로 변환 후 JSONObject에 입력
            sObject.put("num",Integer.toString(COUNT));
            sObject.put("id", id);
            sObject.put("content", content);

            //JSONObject to JSONArray
            return jArray.put(sObject);

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public void writeFile(JSONObject object) {
        String fileTitle = "test.json";
        File file = new File(Environment.getExternalStorageDirectory(), fileTitle);

        try {
            //파일 생성
            if (!file.exists()) {
                file.createNewFile();
            }

            BufferedWriter bw = new BufferedWriter(new FileWriter(file,true));
            bw.write(object.toString());
            
            bw.newLine();
            bw.close();
            
        } catch (IOException e) {
            Log.i("저장오류",e.getMessage());
        }
    }

    
    public void readFile() {

        String fileTitle = "test.json";
        File file = new File(Environment.getExternalStorageDirectory(), fileTitle);

        try {
            BufferedReader reader = new BufferedReader(new FileReader(file));
            String result = "";
            String line;

            while ((line = reader.readLine()) != null) {
                result += line;
            }
            tv.setText(result);
            reader.close();

        } catch (FileNotFoundException e1) {
            Log.i("파일못찾음",e1.getMessage());
        } catch (IOException e2) {
            Log.i("읽기오류",e2.getMessage());
        }
    }


    /**
     * 외부메모리 상태 확인 메서드
     */
    boolean checkExternalStorage() {
        String state = Environment.getExternalStorageState();
        // 외부메모리 상태
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // 읽기 쓰기 모두 가능
            Log.d("test", "외부메모리 읽기 쓰기 모두 가능");
            Toast.makeText(getApplicationContext(),"외부메모리 읽기 쓰기 모두 가능",Toast.LENGTH_SHORT).show();
            return true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){
            //읽기전용
            Log.d("test", "외부메모리 읽기만 가능");
            Toast.makeText(getApplicationContext(),"외부메모리 읽기만 가능",Toast.LENGTH_SHORT).show();
            return false;
        } else {
            // 읽기쓰기 모두 안됨
            Log.d("test", "외부메모리 읽기쓰기 모두 안됨 : "+ state);
            Toast.makeText(getApplicationContext(),"외부메모리 읽기쓰기 모두 안됨 : "+ state,Toast.LENGTH_SHORT).show();
            return false;
        }
    }

}​

 

레이아웃 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"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView
        android:text="id입력"
        android:textSize="15pt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <EditText
        android:id="@+id/idText"
        android:singleLine="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:text="content입력"
        android:textSize="15pt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <EditText
        android:id="@+id/contentText"
        android:singleLine="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/writeBtn"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="입력"/>

    <Button
        android:id="@+id/readBtn"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="적용"/>

    <TextView
        android:id="@+id/tv"
        android:textSize="15pt"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>