본문 바로가기
안드로이드스튜디오 개발

[안드로이드 스튜디오] 오늘의 명언 - assets에 등록된 DB파일을 내부저장소로 복사하기

by jinu957 2021. 5. 12.
728x90

 

이번 포스팅에서는 DB 파일에 대해서 적어보도록 하겠습니다.

 

기본적으로 오늘의 명언 앱은 명언, 고사성어, 속담 등을 DB에 미리 저장해놓고 앱실행 시 데이터를 쿼리해와서 보여주는 방식입니다. 

 

추후 업데이트 시에도 그냥 DB 파일을 배포할 예정이어서 다른 예제들처럼 데이터 파일을 assets에 xml이나 json으로 저장하고 최초 실행 시 내부 저장소 DB에 table을 create하고 데이터를 Insert하는 방식보다 아에 처음부터 assets에 DB파일을 저장하고 최초 실행시 DB파일 자체를 내부저장소로 옮겨서 사용하는 방식으로 하였습니다.

 

앱 특성상 데이터가 명언은 600 여 건, 고사성어는 150 여 건, 속담은 1000 여 건이 넘어가기 때문에 일일이 Insert하는 방식 보다는 통채로 복사해 넣는것이 빠를 것이라고 생각했기 때문입니다. 그리고 요즘 room을 많이 쓰는데 DB파일을 핸들링하는 것이 최소에 쿼리해오는 것 밖에 없어서 그냥 편하게 SQLite DB을 직접 사용했습니다.

 

 

assets에 있는 파일을 내부저장소에 복사하는 방식은 간단합니다.

 

먼저 DB 파일을 핸들링하기 위하여 DataBaseHelper이라는 클래스를 별도로 생성하였고 생성자 부분에 파일을 복사하는 함수를 호출합니다. 복사하는 함수에서는 동일한 저장소에 DB파일이 있는지 체크하고 없으면 copy하고 있으면 그냥 빠져나갑니다.

 

DataBaseHelper.java

 

DataBaseHelper.java 전체 소스

public class DataBaseHelper extends SQLiteOpenHelper
{
    // database 의 파일 경로
    private static String DB_PATH = "";
    private static String DB_NAME = "saying11.db";
    private Context mContext;

    public DataBaseHelper(Context context)
    {
        super(context, DB_NAME, null, 1);

        DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
        this.mContext = context;
        dataBaseCheck();
    }

    private void dataBaseCheck()
    {
        File dbFile = new File(DB_PATH + DB_NAME);

        if (!dbFile.exists())
        {
            dbCopy();
        }
    }

    // db를 assets에서 복사해온다.
    private void dbCopy()
    {
        try
        {
            File folder = new File(DB_PATH);
            if (!folder.exists())
            {
                folder.mkdir();
            }

            InputStream inputStream = mContext.getAssets().open(DB_NAME);
            String out_filename = DB_PATH + DB_NAME;
            OutputStream outputStream = new FileOutputStream(out_filename);
            byte[] mBuffer = new byte[1024];
            int mLength;
            while ((mLength = inputStream.read(mBuffer)) > 0)
            {
                outputStream.write(mBuffer, 0, mLength);
            }
            outputStream.flush();
            ;
            outputStream.close();
            inputStream.close();

        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public synchronized void close()
    {
        if (mDataBase != null)
        {
            mDataBase.close();
        }
        super.close();
    }

    @Override
    public void onCreate(SQLiteDatabase db)
    {
    }

    @Override
    public void onOpen(SQLiteDatabase db)
    {
        super.onOpen(db);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    {
    }
}

위 소스 보시면 클래스 생성자인 public DataBaseHelper(Context context) 부분에 dataBaseCheck() 함수를 호출하고

dataBaseCheck()안에서는 파일이 존재하는지 검사합니다. => if (!dbFile.exists())

 

검사 한 후 파일이 없으면 dbCopy()함수를 호출하고 dbCopy() 함수에서는 assets에 있는 DB파일을 내부저장소로 복사합니다.

복사할때는 InputStream으로 저장된 파일을 읽어 들이고 OutputStream으로 읽은 데이터를 저장해서 파일로 만드는 것이죠

나머지는 별거 없으니 이해하는데 어려움은 없을 듯 합니다.

 

그리고 하나 알아두셔야 할것은 내부저장소의 경로는 data 밑에 data 밑에 패키지 네임 밑에 database 경로에 DB파일이 있어야 한다는 것이죠

그래서 위 소스에 보시면 

DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";

이렇게 지정했다는 것만 아시면 될듯합니다.

 

 

참고로 안드로이드 스튜디오에서 내부저장소의 내용을 보시려면 View 메뉴에서 Tool Windows -> Davice File Explorer을 클릭하시면 아래 그림 오른쪽처럼 내부저장소의 파일을 찾아보실 수 있습니다.

여기서 data/data/자기패키지명/database 을 열어보시면 파일이 저장되어있는 것을 확인 하실 수 있습니다.

 

 

 

혹시 앱이 궁금하신 분은 아래 링크로 들어가시면 다운받을 수 있으시니 한번 다운받아서 설치해보시고 리뷰 남겨주시면 감사하겠습니다. ^^;;;

https://play.google.com/store/apps/details?id=com.withu.todayssaying

 

오늘의 명언(명언, 고사성어, 속담) - Google Play 앱

오늘 하루 도움이 되는 명언을 선택해 드리며 명언, 고사성어, 속담 등을 지변 지인들과 나누어 보세요

play.google.com

 

728x90

댓글