2012-01-11 6 views
1

Android 애플리케이션의 assets 폴더에서 약 80MB의 파일을 SD 카드로 복사하려고합니다.메모리 부족 오류없이 응용 프로그램 자산 폴더에서 SD 카드로 큰 파일을 작성하는 방법은 무엇입니까?

파일이 다른 apk입니다. 여러 가지 이유로 나는 이런 식으로해야만 온라인 apk에 링크하거나 Android 마켓에 넣을 수 없습니다.

이 응용 프로그램은 작은 apks에서는 제대로 작동하지만이 큰 응용 프로그램에서는 메모리 부족 오류가 발생합니다.

정확히 어떻게 작동하는지 잘 모르겠지만 메모리에 80 메가 바이트를 전부 쓰려고합니다.

try { 
       int length = 0; 
       newFile.createNewFile(); 

       InputStream inputStream = ctx.getAssets().open(
         "myBigFile.apk"); 
       FileOutputStream fOutputStream = new FileOutputStream(
         newFile); 
       byte[] buffer = new byte[inputStream.available()]; 
       while ((length = inputStream.read(buffer)) > 0) { 
        fOutputStream.write(buffer, 0, length); 
       } 
       fOutputStream.flush(); 
       fOutputStream.close(); 
       inputStream.close(); 
      } catch (Exception ex) { 
       if (ODP_App.getInstance().isInDebugMode()) 
        Log.e(TAG, ex.toString()); 
      } 

나는이 흥미로운 발견 - 내가 오해 한 않는 이 A question about an out of memory issue with Bitmaps

, 비트 맵의 ​​경우, BitmapFactory.Options를 사용하여 메모리 사용을 줄이기 위해 스트림을 분할하는 몇 가지 방법이있을 나타납니다.

내 시나리오에서 이것이 가능합니까 아니면 다른 가능한 해결책이 있습니까?

+2

버퍼가 너무 커서 전체 파일을 메모리로 읽으려고합니다. 나는'inputStream.available()'이 전체 크기를 얻는다 고 추측한다. 1024 (또는 무언가)로 변경하십시오. – musefan

+0

하나의 방법으로 전체 APK를 단일 스트림으로 전송하는 대신 APK에서 각 파일을 전송해야 할 수 있습니다. AFAIK, apk는 ZIP 형식이기 때문에 zip API 및 Stream API에 대한 해킹이 필요할 수 있습니다. – kosa

+0

안녕하세요. 당신이 옳았. inputStream.available()은 입력 스트림에있는 파일의 양을 바이트 단위로 가져옵니다. 나는 그 방법이 정확히 여기에 게시되기 전에 읽어야한다고 생각한다. 귀하의 의견에 감사드립니다. 버퍼 크기 변경 작업. –

답변

7

트릭은 전체 파일을 한 번에 읽지 않고 작은 청크로 읽고 다음 청크를 작성하여 동일한 메모리 세그먼트로 읽는 것입니다. 다음 버전에서는 1K 청크로 읽습니다. 예를 들어, 올바른 청크 크기를 결정해야합니다.

try { 
    int length = 0; 
    newFile.createNewFile(); 

    InputStream inputStream = ctx.getAssets().open(
      "myBigFile.apk"); 
    FileOutputStream fOutputStream = new FileOutputStream(
      newFile); 
    //note the following line 
    byte[] buffer = new byte[1024]; 
    while ((length = inputStream.read(buffer)) > 0) { 
     fOutputStream.write(buffer, 0, length); 
    } 
    fOutputStream.flush(); 
    fOutputStream.close(); 
    inputStream.close(); 
} catch (Exception ex) { 
    if (ODP_App.getInstance().isInDebugMode()) 
     Log.e(TAG, ex.toString()); 
} 
+0

1024는 임의의 값입니다. 내 대답을 읽으면 훨씬 큰 값 (16k 또는 128k 등이 될 수 있습니다)을 사용할 수 있습니다. – njzk2

+0

"예를 들어 설명 했으므로주의해야합니다. 오른쪽 청크 크기 " –

+0

큰 설명과 예제를 제공해 주셔서 감사합니다. 완벽하게 일했습니다. –

2

전체 파일을 메모리로 읽어 들이지 마십시오. 한 번에 64k를 읽은 다음 파일을 쓰고 파일 끝에 도달 할 때까지 반복하십시오. 또는 Apache Commons IO의 IOUtils를 사용하십시오.

+0

답변 해 주셔서 감사합니다. 당신이 말한 것은 정확하지만 Aleks G의 답변을 받아 들였습니다. 왜냐하면 그는 더 자세한 예제를 제공했기 때문입니다. 다시 한번 감사드립니다. –

관련 문제