Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách đọc file từ thư mục assets trên Android

Giới thiệu

Thư mục assets/ dùng để lưu trữ file tĩnh (JSON, text, font, HTML, CSV...) được đóng gói cùng APK. Không giống res/raw/, assets giữ nguyên cấu trúc thư mục và tên file, không bị compile thành resource ID. Bài viết hướng dẫn đọc file từ assets bằng AssetManager.

Các bước thực hiện

Bước 1: Tạo dự án mới

Android Studio → File → New Project → Empty View Activity.

Bước 2: Tạo thư mục assets và thêm file

  1. Chuột phải vào module app → New → Folder → Assets Folder.
  2. Chuột phải vào thư mục assets vừa tạo → New → File → đặt tên quotes.txt.
  3. Nhập nội dung:
"Darkness cannot drive out darkness: only light can do that. 
Hate cannot drive out hate: only love can do that."
— Martin Luther King Jr.

Bước 3: Thiết kế giao diện (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="24dp"
    android:gravity="center"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnReadFile"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Đọc file từ assets" />

    <TextView
        android:id="@+id/tvContent"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:layout_marginTop="16dp"
        android:padding="12dp"
        android:textSize="16sp"
        android:gravity="center"
        android:background="@android:color/darker_gray"
        tools:text="Nội dung file sẽ hiển thị ở đây" />
</LinearLayout>

Bước 4: Code đọc file (MainActivity.java / MainActivity.kt)

Java (sử dụng try-with-resources):

package com.example.readassets;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class MainActivity extends AppCompatActivity {

    private TextView tvContent;
    private Button btnReadFile;

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

        tvContent = findViewById(R.id.tvContent);
        btnReadFile = findViewById(R.id.btnReadFile);

        btnReadFile.setOnClickListener(v -> readFileFromAssets());
    }

    private void readFileFromAssets() {
        try (InputStream inputStream = getAssets().open("quotes.txt");
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {

            StringBuilder stringBuilder = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line).append("\n");
            }
            tvContent.setText(stringBuilder.toString().trim());

        } catch (IOException e) {
            e.printStackTrace();
            tvContent.setText("Lỗi đọc file: " + e.getMessage());
        }
    }
}

Kotlin (sử dụng extension function):

package com.example.readassets

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.readassets.databinding.ActivityMainBinding
import java.io.BufferedReader

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.btnReadFile.setOnClickListener {
            readFileFromAssets()
        }
    }

    private fun readFileFromAssets() {
        try {
            val inputStream = assets.open("quotes.txt")
            val content = inputStream.bufferedReader().use { it.readText() }
            binding.tvContent.text = content.trim()
        } catch (e: Exception) {
            binding.tvContent.text = "Lỗi đọc file: ${e.message}"
        }
    }
}

Đọc file JSON từ assets (ứng dụng thực tế)

File: assets/config.json

{
  "api_base_url": "https://api.example.com",
  "timeout": 30000,
  "features": ["dark_mode", "offline_sync", "push_notifications"]
}

Code parse JSON (cần dependency Gson/Moshi):

// Kotlin + Moshi
private fun loadConfig(): AppConfig? {
    return try {
        val json = assets.open("config.json").bufferedReader().use { it.readText() }
        Moshi.Builder().build().adapter(AppConfig::class.java).fromJson(json)
    } catch (e: Exception) {
        null
    }
}

data class AppConfig(
    val api_base_url: String,
    val timeout: Int,
    val features: List<String>
)

Assets vs res/raw

Đặc điểmassets/res/raw/
Cấu trúc thư mụcGiữ nguyên (subfolders OK)Phẳng (không có subfolder)
Truy cậpAssetManager.open()Resources.openRawResource(R.raw.xxx)
Tên fileBất kỳ (có dấu cách, chữ hoa)Chỉ [a-z0-9_]
Compile timeKhông generate R.idGenerate R.raw.xxx
Kích thước fileKhông giới hạnKhông giới hạn

Lưu ý quan trọng

  • File trong assets không được nén khi build APK (trừ khi dùng aaptOptions { noCompress "txt", "json" }).
  • Đọc file lớn nên dùng background thread (coroutine/RxJava) để không block UI thread.
  • Đóng InputStream sau khi dùng (try-with-resources hoặc .use { } Kotlin).
  • Không thể ghi file vào assets lúc runtime (read-only). Cần ghi vào internal storage (context.filesDir).