IT, Programming/Android

안드로이드 Asset file 사용하기 (모두 읽어오기)

우주먼지 [宇宙塵, cosmic dust] 2014. 8. 29. 11:22

 안드로이드 Asset file 사용하기 (파일 읽어오기, 디렉토리 읽어오기, 재귀함
수를 이용하여 모두 읽어오기)

안드로이드 개발을 하다 보면 asset에 파일을 넣어서 실행타임에 불러서 사용하는 경우가 종종 있다.

 

예를 들면 db 파일을 저장했다가 앱의 database 폴더에 카피 해 넣는다던지, 아니면... 뭐 어쨌든 asset에서 파일을 넣고 사용할 필요가 있었으니깐 여기까지 검색해서 들어온거 아닐까... 하는 생각이 들므로 더이상의 자세한 예시는 생략한다김성모화백 빙의.

 

일단 asset에 파일이 들어 있는 예시 이미지를 한 장 보자. 

 

 

 

뭐 이렇게 올라가 있다고 치자근데 화질이 왜 이렇게 구린거야...하지만 귀찮으니깐 그냥 넘어가자. 여기에는 'font'라는 디렉토리도 있고 'icon_payment'라는 디렉토리도 있고 그 밑에는 'Maestro-1.png'라는 이미지도 있다. 그리고 'asset' 바로 밑에는 'dna.png'라는 파일도 있군.

 

일단 문맥의 흐림상 모두 예상하였겠지만 가장 쉬운 'dna.png'를 참조하는 코드를 보자.

try {
    AssetManager assetMgr = getAssets();
    InputStream is = assetMgr.open("dna.png");
    
    // TODO: 
} catch (IOException e) {
    e.printStackTrace();
}

Asset에서 파일명을 알고 있는 파일 읽어오기

 

 

InputStream까지만 얻어오면 나머지는 알아서 잘들 하실거니 더이상의 자세한 설명은 생략한다.

 

문맥의 흐름상 모두 예상하였겠지만 그렇다면 저기 하위디렉토리 밑에 들어가 있는 'Maestro-1.png'는 어떻게 읽어들이는가. 그것은... 똑같다. 뭐 똑같다고 해도 상관 없을 정도로 비슷하다. 그냥 경로만 더 적어주면 되기 때문이다.

try {
    AssetManager assetMgr = getAssets();
    InputStream is = assetMgr.open("icon_payment/Maestro-1.png");
    
    // TODO: 
} catch (IOException e) {
    e.printStackTrace();
}

Asset에서 경로명을 알고 있는 하위 디렉토리의 파일 읽어오기

 

 

이번에도 문맥의 흐름상.. 자꾸 파일명/경로명을 '알고 있는'을 강조한걸 보면 몰라도 알아올 수 있다는 걸 눈치챘을거다. 그렇다 AssetManager로부터 파일 목록을 가져올 수 있다. 그 코드는 하기와 같다.

	try {
		AssetManager assetMgr = getAssets();
		String[] list = assetMgr.list("/");
		
		// TODO: 
		
	} catch (IOException e) {
		e.printStackTrace();
	}

AssetManager로부터 파일 목록 받아오기

 

 

이렇게 하면  String array인 'list'에 파일 목록을 전부 가져 올 수 있다. 파일 목록을 받아왔으니 알아서 응용하면 되겠다.

 

그런데 문제가 생겼네. 목록은 받아왔는데 이게 일반파일인지 디렉토리인지 어떻게 알아내지? 특별히 알려주는 함수는 제공하지 않는것 같으나 뭐 응용을하면 대충 알아낼 수 있다.

 

바로전 예시에 나왔던  AssetManager .list("/") 함수를 이용하는거다. 인자에 경로는 넣어두면 해당 경로의 파일 목록을 넘겨주는 함수인데 여기서 넘겨주는 string array의 length가 0보다 크면 디렉토리라는 증거이다. 0일 경우 확장자가있으면 파일이고 확장자도 없으면 파일인지 디렉토리 인지 모른다모른다 하더라도 하위에 다른 파일을 갖고있는건 아니니깐 상관없다.

 

아래는 그 예시이다.

    AssetManager assetMgr = this.getAssets();
    String assets[] = null;
    try {
        assets = assetMgr.list("/");
        
        for(String element : assets) {
        	String[] sub = assetMgr.list(element);
        	
        	if(sub.length > 0) {
        		// TODO: 서브파일이 존재, 디렉토리
        	}
        	else {
        		// TODO: 서브파일 없음, 파일이거나 빈 디렉토리
        	}
        }
        
    } catch (IOException e) {
       e.printStackTrace();
    }

서브파일 존재여부 구분하기 (≒ 파일/디렉토리 구분하기)

 

이제 asset의 파일들을 이용하는 기본적인 방법들을 알았으니 마지막으로 상기 코드들의 조합으로 재귀호출(recursive call) 함수를 만들어 asset의 파일을 모두~ 전부~ 가져오는 코드를 만들어보자.

 

패스 지정하고 뭐 이런거는 귀찮으니깐 카피를 할 대상 경로를 앱의 파일 디렉토리로 정해야겠다야이 게으름뱅이야. 즉 getFileDir().getAbsolutePath()로 하겠다.

 

아래는 그 코드이다.

	public void copyAssetAll(String srcPath) {
	    AssetManager assetMgr = this.getAssets();
	    String assets[] = null;
	    try {
	        assets = assetMgr.list(srcPath);
	        if (assets.length == 0) {
	            copyFile(srcPath);
	        } else {
	            String destPath = getFilesDir().getAbsolutePath() + File.separator + srcPath;
	            
	            File dir = new File(destPath);
	            if (!dir.exists())
	                dir.mkdir();
	            for (String element : assets) {
	            	copyAssetAll(srcPath + File.separator + element);
	            }
	        }
	    } 
	    catch (IOException e) {
	       e.printStackTrace();
	    }
	}
	 
	
	public void copyFile(String srcFile) {
	    AssetManager assetMgr = this.getAssets();
	 
	    InputStream is = null;
	    OutputStream os = null;
	    try {
	    	String destFile = getFilesDir().getAbsolutePath() + File.separator + srcFile;
	       
	    	is = assetMgr.open(srcFile);
	        os = new FileOutputStream(destFile);
	 
	        byte[] buffer = new byte[1024];
	        int read;
	        while ((read = is.read(buffer)) != -1) {
	            os.write(buffer, 0, read);
	        }
	        is.close();
	        os.flush();
	        os.close();
	        
	    } 
	    catch (IOException e) {
	    	e.printStackTrace();
		}
	}

Asset의 파일을 모두 복사하기 위한 재귀 함수

 

	try {
		AssetManager assetMgr = getAssets();
		String[] rootList = assetMgr.list("/");
		
		for(String element : rootList) {
			copyAssetAll(element);
		}
	}
	catch(IOException e) {
		e.printStackTrace();
	}

작성한 재귀함수를 이용하여 Asset 파일을 모두 복사하기

 

이상으로 Asset의 file을 이용하기위한 더 이상의 자세한 설명은 생략한다