如何在 Android 中读取文本文件

在 Android 开发中,读取本地存储或应用程序资源中的文本文件是一个常见的需求。无论是从 res/raw 文件夹加载资源文件,还是从设备的外部存储读取用户数据,掌握如何正确地读取文本文件都是十分重要的。

本文将详细介绍如何在 Android 中使用不同的方法来读取文本文件,并处理可能出现的异常情况。

使用 InputStream 读取资源文件

首先,我们来看一个简单的例子,展示如何从应用程序的 res/raw 文件夹中读取一个文本文件。假设我们在 res/raw 文件夹下有一个名为 sample.txt 的文件。

public class MainActivity extends AppCompatActivity {

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

        // 获取资源文件的 InputStream
        InputStream inputStream = getResources().openRawResource(R.raw.sample);
        String fileContent = readTextFile(inputStream);

        // 将读取的内容显示在 TextView 中
        TextView textView = findViewById(R.id.textView);
        textView.setText(fileContent);
    }

    private String readTextFile(InputStream inputStream) {
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line).append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return stringBuilder.toString();
    }
}

在这个例子中,我们使用 getResources().openRawResource(R.raw.sample) 来获取资源文件的 InputStream,然后通过 readTextFile() 方法读取文件内容。注意,为了防止资源泄漏,我们在 finally 块中关闭了 BufferedReader

从外部存储读取文本文件

除了读取应用内部的资源文件外,有时我们还需要从设备的外部存储(如 SD 卡)读取用户数据。这里展示如何从指定路径读取一个文本文件。

首先,在 AndroidManifest.xml 中添加读取外部存储的权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

然后,我们需要在运行时请求这个权限(适用于 Android 6.0 及以上版本):

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE);
}

最后,编写读取文件的代码:

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_CODE = 100;

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

        // 检查权限并读取文件
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            readFileFromExternalStorage();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == REQUEST_CODE && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            readFileFromExternalStorage();
        } else {
            Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
        }
    }

    private void readFileFromExternalStorage() {
        File file = new File(Environment.getExternalStorageDirectory(), "sample.txt");
        if (file.exists()) {
            StringBuilder stringBuilder = new StringBuilder();
            BufferedReader reader = null;

            try {
                reader = new BufferedReader(new FileReader(file));
                String line;
                while ((line = reader.readLine()) != null) {
                    stringBuilder.append(line).append("\n");
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            // 将读取的内容显示在 TextView 中
            TextView textView = findViewById(R.id.textView);
            textView.setText(stringBuilder.toString());
        } else {
            Toast.makeText(this, "文件不存在", Toast.LENGTH_SHORT).show();
        }
    }
}

在这个例子中,我们首先检查了是否已经获得了读取外部存储的权限。如果没有获得权限,则请求用户授权。一旦权限被授予,我们就尝试从指定路径读取文件内容。

处理异常

在读取文件时,可能会遇到各种异常情况,例如文件不存在、权限不足等。因此,在读取文件的过程中,我们需要适当地处理这些异常,以确保应用的稳定性和用户体验。

try {
    // 读取文件的代码...
} catch (IOException e) {
    Log.e("MainActivity", "读取文件时发生错误: " + e.getMessage());
    Toast.makeText(this, "无法读取文件,请检查权限或文件路径。", Toast.LENGTH_SHORT).show();
}

在这个例子中,我们使用 try-catch 块来捕获并处理 IOException 异常。当出现异常时,我们在日志中记录错误信息,并通过 Toast 提示用户。

总结

通过以上步骤,我们成功地展示了如何在 Android 中读取文本文件,并处理可能出现的异常情况。无论是从应用内部的资源文件夹还是设备的外部存储读取数据,都可以使用类似的方法来实现。

读取文件是一个常见的需求,掌握这些技巧将有助于提高你的 Android 开发技能。