자산에서 파일을 읽습니다


178
public class Utils {
    public static List<Message> getMessages() {
        //File file = new File("file:///android_asset/helloworld.txt");
        AssetManager assetManager = getAssets();
        InputStream ims = assetManager.open("helloworld.txt");    
     }
}

이 코드를 사용하여 자산에서 파일을 읽으려고합니다. 나는 이것을하기 위해 두 가지 방법을 시도했다. 첫째, 사용시 File수신 방법을 사용할 FileNotFoundExceptionAssetManager getAssets()인식되지 않습니다. 여기에 해결책이 있습니까?

답변:


225

다음은 버퍼링 읽기 확장 / 수정 활동에 필요한 작업을 수행하는 것입니다.

BufferedReader reader = null;
try {
    reader = new BufferedReader(
        new InputStreamReader(getAssets().open("filename.txt")));

    // do reading, usually loop until end of file reading  
    String mLine;
    while ((mLine = reader.readLine()) != null) {
       //process line
       ...
    }
} catch (IOException e) {
    //log the exception
} finally {
    if (reader != null) {
         try {
             reader.close();
         } catch (IOException e) {
             //log the exception
         }
    }
}

편집 : 귀하의 질문이 활동 이외의 방법으로 수행되는 경우 내 대답은 쓸모가 없습니다. 귀하의 질문이 단순히 자산에서 파일을 읽는 방법이라면 대답은 위의 것입니다.

업데이트 :

형식을 지정하는 파일을 열려면 간단히 다음과 같이 InputStreamReader 호출에 형식을 추가하십시오.

BufferedReader reader = null;
try {
    reader = new BufferedReader(
        new InputStreamReader(getAssets().open("filename.txt"), "UTF-8")); 

    // do reading, usually loop until end of file reading 
    String mLine;
    while ((mLine = reader.readLine()) != null) {
       //process line
       ...
    }
} catch (IOException e) {
    //log the exception
} finally {
    if (reader != null) {
         try {
             reader.close();
         } catch (IOException e) {
             //log the exception
         }
    }
}

편집하다

@Stan이 의견에서 말했듯이, 내가주는 코드는 줄을 요약하지 않습니다. mLine모든 패스가 교체됩니다. 내가 쓴 이유 //process line입니다. 파일에는 일종의 데이터 (예 : 연락처 목록)가 포함되어 있으며 각 줄은 별도로 처리해야한다고 가정합니다.

어떤 종류의 처리없이 파일을 단순히로드하려는 경우 mLine각 패스를 사용 StringBuilder()하고 추가하여 각 패스 에서 합계 해야합니다.

다른 편집

@Vincent의 의견에 따르면 finally블록을 추가했습니다 .

또한 Java 7 이상 에서는 최신 Java try-with-resourcesAutoCloseableCloseable기능 을 사용하는 데 사용할 수 있습니다 .

문맥

의견에서 @LunarWatcher getAssets()classin context입니다. 따라서 외부에서 호출하는 경우이를 activity참조하고 컨텍스트 인스턴스를 활동에 전달해야합니다.

ContextInstance.getAssets();

이것은 @Maneesh의 답변에 설명되어 있습니다. 그래서 이것이 당신에게 도움이된다면 그의 대답을지지했습니다. 왜냐하면 그것은 그것을 지적한 사람이기 때문입니다.


2
@Stan에 의견을 적고 작성자가 업데이트 여부를 결정하도록합니다. 편집은 의미를 바꾸지 않고 선명도를 향상시키기위한 것입니다. 코드 개정은 항상 주석으로 먼저 게시해야합니다.
KyleMit

2
귀하의 코드는 스트림을 닫고 적시에 리소스를 해제한다고 보증하지 않습니다. 사용하는 것이 좋습니다 finally {reader.close();}.
Vincent Cantin

2
위 코드가 ADT의 오류 인 "reader.close ();"를 나타내는 것이 도움이된다고 생각합니다. line은 다른 try-catch 블록에 넣어야합니다. 이 스레드를 확인하십시오 : stackoverflow.com/questions/8981589/… :)
JakeP

1
getAssets는 Context의 클래스이므로 액티비티 외부에서 사용하려면 Context를 호출해야합니다. 활동 밖에서는context.getAssets(.....)
Zoe

1
업데이트에 따라 (btw 추가 덕분에) 정적 필드에 컨텍스트가있는 것은 메모리 누수입니다. 주의해서 사용하고 올바르게 청소해야합니다. 그렇지 않으면 앱에 큰 영향을 줄 수있는 메모리 누수가 발생합니다.
Zoe

65
getAssets()

는 다른 클래스의 Activity 에서만 작동 Context합니다.

Utils 클래스 의 생성자 에게 매개 변수로 응용 프로그램 (추악한 방법) 또는 컨텍스트 컨텍스트 참조를 전달하십시오. 이를 사용하면 Utils 클래스에서 getAsset ()을 사용하십시오.


1
Context의 하위 클래스 인 Activity에서 많은 활동을하는 모든 항목에서 작동합니다.
Jeremy Logan

방금 쓴 글 Context입니다.
user370305

@ user370305 어떻게 InputStream을 FileInputStream으로 변환 할 수 있습니까?
hotHead

@ user370305 이것이 어떤 방법으로 추악한가요?
Sevastyan Savanyuk

결과를 고려하지 않고 UI 객체를 전달하는 것은 일반적으로 나쁜 습관입니다. 주의하지 않으면 메모리 누수가 발생하거나 죽은 컨텍스트를 사용할 수 있습니다. 주제에 대한 좋은 읽을 거리 : android.jlelse.eu/memory-leak-in-android-4741a7fcb570
milosmns

49

안하는 것보다 늦게하는 것이 낫다.

상황에 따라 파일을 한 줄씩 읽는 데 어려움이있었습니다. 아래 방법은 지금까지 내가 찾은 최고이며 권장합니다.

용법: String yourData = LoadData("YourDataFile.txt");

어디 YourDataFile.txt가 에 거주하는 가정 자산 /

 public String LoadData(String inFile) {
        String tContents = "";

    try {
        InputStream stream = getAssets().open(inFile);

        int size = stream.available();
        byte[] buffer = new byte[size];
        stream.read(buffer);
        stream.close();
        tContents = new String(buffer);
    } catch (IOException e) {
        // Handle exceptions here
    }

    return tContents;

 }

내 반환 문자열은 android.content.res.AssetManager$AssetInputStream@4195dfa0입니다.
Boldijar Paul

여기에 res.AssetManager $ AssetInputStream @ ...이 반환되는 특별한 이유는 무엇입니까?
Bigs

먼저 버퍼와 문자열에 메모리를 이중 할당합니다. 더 큰 파일에는 작동하지 않습니다.
JaakL

1
버퍼에 크기를 할당하는 완벽한 방법 stream.available().
Kasim Rangwala

39
public String ReadFromfile(String fileName, Context context) {
    StringBuilder returnString = new StringBuilder();
    InputStream fIn = null;
    InputStreamReader isr = null;
    BufferedReader input = null;
    try {
        fIn = context.getResources().getAssets()
                .open(fileName, Context.MODE_WORLD_READABLE);
        isr = new InputStreamReader(fIn);
        input = new BufferedReader(isr);
        String line = "";
        while ((line = input.readLine()) != null) {
            returnString.append(line);
        }
    } catch (Exception e) {
        e.getMessage();
    } finally {
        try {
            if (isr != null)
                isr.close();
            if (fIn != null)
                fIn.close();
            if (input != null)
                input.close();
        } catch (Exception e2) {
            e2.getMessage();
        }
    }
    return returnString.toString();
}

BufferedReader를 닫으면 InputStreanReader 및 InputStream도 자동으로 닫는 것보다 낫습니다. 그것이 당신을 위해 핸들을 만들지 않기 때문에 input = new BufferedReader(new InputStreamReader(fIn));.
trans

3
마지막에 모든 리소스를 종료하기 위해 별도의 try / catch 블록을 만드는 것이 좋습니다. 이전에 다른 리소스를 닫으려고 시도하면 예외가 발생하는 경우 다른 리소스를 닫히지 않을 수 있으므로 모든 것을 하나로 묶지 마십시오.
Reece

9
AssetManager assetManager = getAssets();
InputStream inputStream = null;
try {
    inputStream = assetManager.open("helloworld.txt");
}
catch (IOException e){
    Log.e("message: ",e.getMessage());
}

8

kotlin을위한 한 줄 솔루션 :

fun readFileText(fileName: String): String {
    return assets.open(fileName).bufferedReader().use { it.readText() }
}

7

getAssets() Activity 클래스 내에서 호출 할 때 메소드가 작동합니다.

비 활동 클래스에서이 메소드를 호출하는 경우 Activity 클래스에서 전달 된 컨텍스트에서이 메소드를 호출해야합니다. 아래는 메소드에 액세스 할 수있는 줄입니다.

ContextInstance.getAssets();

ContextInstance Activity 클래스의 이것으로 전달 될 수 있습니다.


5

파일 읽기 및 쓰기는 항상 장황하고 오류가 발생하기 쉽습니다. 이 답변을 피하고 대신 Okio를 사용하십시오.

public void readLines(File file) throws IOException {
  try (BufferedSource source = Okio.buffer(Okio.source(file))) {
    for (String line; (line = source.readUtf8Line()) != null; ) {
      if (line.contains("square")) {
        System.out.println(line);
      }
    }
  }
}

1
왜 이것이 더 미학적이고 짧게 보이는지 아십니까? 적어도 코드의 절반은 생략했기 때문입니다. 생략 된 부분 : 1) IOExceptiontry / catch 블록 2) 예외가 발생한 경우 스트림 닫기 3)이 코드는 전체 파일이 아닌 단일 행을 읽습니다. 성능면 에서이 라이브러리는 분명히 그 종류 중 하나입니다. 자, 여전히 "이 답변들"을 피하고 파일을 읽기 위해 Okio를 구현해야한다고 말씀해 주시겠습니까? 이미 앱의 일부가 아닌 한 대답은 아니요입니다.
Farid

내 답변을 업데이트했습니다.
Saket

4

자산에서 파일을 읽는 방법은 다음과 같습니다.

/**
 * Reads the text of an asset. Should not be run on the UI thread.
 * 
 * @param mgr
 *            The {@link AssetManager} obtained via {@link Context#getAssets()}
 * @param path
 *            The path to the asset.
 * @return The plain text of the asset
 */
public static String readAsset(AssetManager mgr, String path) {
    String contents = "";
    InputStream is = null;
    BufferedReader reader = null;
    try {
        is = mgr.open(path);
        reader = new BufferedReader(new InputStreamReader(is));
        contents = reader.readLine();
        String line = null;
        while ((line = reader.readLine()) != null) {
            contents += '\n' + line;
        }
    } catch (final Exception e) {
        e.printStackTrace();
    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException ignored) {
            }
        }
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException ignored) {
            }
        }
    }
    return contents;
}

이것은 좋은 대답이지만 문자열 연결을 사용하는 것은 좋지 않습니다. 대신 StringBuilder를 사용하십시오. StringBuilder contentBuilder = 새로운 StringBuilder (); while ((line = reader.readLine ())! = null) {builder.append ( "\ n"). append (line); } 그리고 마지막으로 다음과 같이하여 새 String 객체를 만들 수 있습니다. content = contentBuilder.toString ();
Barterio

4

파일에서 내용을로드 할 수 있습니다. 파일이 자산 폴더에 있다고 가정하십시오.

public static InputStream loadInputStreamFromAssetFile(Context context, String fileName){
    AssetManager am = context.getAssets();
    try {
        InputStream is = am.open(fileName);
        return is;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

public static String loadContentFromFile(Context context, String path){
    String content = null;
    try {
        InputStream is = loadInputStreamFromAssetFile(context, path);
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        content = new String(buffer, "UTF-8");
    } catch (IOException ex) {
        ex.printStackTrace();
        return null;
    }
    return content;
}

이제 다음과 같이 함수를 호출하여 컨텐츠를 얻을 수 있습니다.

String json= FileUtil.loadContentFromFile(context, "data.json");

data.json을 고려하면 Application \ app \ src \ main \ assets \ data.json에 저장됩니다.


3

MainActivity.java에서

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

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

        AssetsReader assetsReader = new AssetsReader(this);
        if(assetsReader.getTxtFile(your_file_title)) != null)
        {
            tvView.setText(assetsReader.getTxtFile(your_file_title)));
        }
    }

또한 모든 작업을 수행하는 별도의 클래스를 만들 수 있습니다

public class AssetsReader implements Readable{

    private static final String TAG = "AssetsReader";


    private AssetManager mAssetManager;
    private Activity mActivity;

    public AssetsReader(Activity activity) {
        this.mActivity = activity;
        mAssetManager = mActivity.getAssets();
    }

    @Override
    public String getTxtFile(String fileName)
    {
        BufferedReader reader = null;
        InputStream inputStream = null;
        StringBuilder builder = new StringBuilder();

        try{
            inputStream = mAssetManager.open(fileName);
            reader = new BufferedReader(new InputStreamReader(inputStream));

            String line;

            while((line = reader.readLine()) != null)
            {
                Log.i(TAG, line);
                builder.append(line);
                builder.append("\n");
            }
        } catch (IOException ioe){
            ioe.printStackTrace();
        } finally {

            if(inputStream != null)
            {
                try {
                    inputStream.close();
                } catch (IOException ioe){
                    ioe.printStackTrace();
                }
            }

            if(reader != null)
            {
                try {
                    reader.close();
                } catch (IOException ioe)
                {
                    ioe.printStackTrace();
                }
            }
        }
        Log.i(TAG, "builder.toString(): " + builder.toString());
        return builder.toString();
    }
}

내 의견으로는 인터페이스를 만드는 것이 낫지 만 필수는 아닙니다.

public interface Readable {
    /**
     * Reads txt file from assets
     * @param fileName
     * @return string
     */
    String getTxtFile(String fileName);
}

2

Activity 이외의 다른 클래스를 사용하는 경우 다음과 같이 할 수 있습니다.

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader( YourApplication.getInstance().getAssets().open("text.txt"), "UTF-8"));

2

Kotlin을 사용하면 다음을 수행하여 Android의 자산에서 파일을 읽을 수 있습니다.

try {
    val inputStream:InputStream = assets.open("helloworld.txt")
    val inputString = inputStream.bufferedReader().use{it.readText()}
    Log.d(TAG,inputString)
} catch (e:Exception){
    Log.d(TAG, e.toString())
}

2

너무 늦었지만 복숭아 답변을 찾는 다른 사람들을 위해 :

public static String loadAssetFile(Context context, String fileName) {
    try {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(context.getAssets().open(fileName)));
        StringBuilder out= new StringBuilder();
        String eachline = bufferedReader.readLine();
        while (eachline != null) {
            out.append(eachline);
            eachline = bufferedReader.readLine();
        }
        return out.toString();
    } catch (IOException e) {
        Log.e("Load Asset File",e.toString());
    }
    return null;
}

1

cityfile.txt

   public void getCityStateFromLocal() {
        AssetManager am = getAssets();
        InputStream inputStream = null;
        try {
            inputStream = am.open("city_state.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
        ObjectMapper mapper = new ObjectMapper();
        Map<String, String[]> map = new HashMap<String, String[]>();
        try {
            map = mapper.readValue(getStringFromInputStream(inputStream), new TypeReference<Map<String, String[]>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        ConstantValues.arrayListStateName.clear();
        ConstantValues.arrayListCityByState.clear();
        if (map.size() > 0)
        {
            for (Map.Entry<String, String[]> e : map.entrySet()) {
                CityByState cityByState = new CityByState();
                String key = e.getKey();
                String[] value = e.getValue();
                ArrayList<String> s = new ArrayList<String>(Arrays.asList(value));
                ConstantValues.arrayListStateName.add(key);
                s.add(0,"Select City");
                cityByState.addValue(s);
                ConstantValues.arrayListCityByState.add(cityByState);
            }
        }
        ConstantValues.arrayListStateName.add(0,"Select States");
    }
 // Convert InputStream to String
    public String getStringFromInputStream(InputStream is) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        String line;
        try {
            br = new BufferedReader(new InputStreamReader(is));
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return sb + "";

    }

링크는 이제 다음을 반환합니다File no longer available That file has now been permanently removed and cannot be recovered
gregn3

1

스캐너 클래스는이를 단순화 할 수 있습니다.

        StringBuilder sb=new StringBuilder();
        Scanner scanner=null;
        try {
            scanner=new Scanner(getAssets().open("text.txt"));
            while(scanner.hasNextLine()){
                sb.append(scanner.nextLine());
                sb.append('\n');
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(scanner!=null){try{scanner.close();}catch (Exception e){}}
        }
        mTextView.setText(sb.toString());

이 두 줄을 병합 할 수 있습니다. sb.append (scanner.nextLine ()); sb.append ( '\ n'); sb.appendln (scanner.nextLine ());
Mojtaba

0

@HpTerm 답변 Kotlin 버전 :

private fun getDataFromAssets(): String? {

    var bufferedReader: BufferedReader? = null
    var data: String? = null

    try {
        bufferedReader = BufferedReader(
            InputStreamReader(
                activity?.assets?.open("Your_FILE.html"),     
                "UTF-8"
            )
        )                  //use assets? directly if in activity

       var mLine:String = bufferedReader?.readLine()
        while (mLine != null) {
            data+= mLine
            mLine=bufferedReader.readLine()
        }

    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        try {
            bufferedReader?.close()
        } catch (e: Exception) {
           e.printStackTrace()
        }
    }
    return data
}

현재 이것은 문자열 앞에 null을 추가합니다. 필요한 변경 : var mLine:String해야 var mLine:String? var data: String?해야한다 var data = ""반환 형식이되어야합니다String
fupduck

0

여기에 얻을 수있는 방법이다 InputStream에있는 파일에 대한 assets없이 폴더를 Context, Activity, Fragment또는 Application. 그것으로부터 데이터를 얻는 방법은 당신에게 InputStream달려 있습니다. 여기에 다른 답변에 대한 제안이 많이 있습니다.

코 틀린

val inputStream = ClassLoader::class.java.classLoader?.getResourceAsStream("assets/your_file.ext")

자바

InputStream inputStream = ClassLoader.class.getClassLoader().getResourceAsStream("assets/your_file.ext");

커스텀 ClassLoader이 진행 중이면 모든 베팅이 해제됩니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.