ภาพรวม
ตัวอย่างนี้สาธิตการบันทึกรายการข้อมูล (List) ลงในไฟล์ Text บน Internal Storage และอ่านกลับมาแสดงผล ใช้คลาส File, FileWriter, BufferedReader สำหรับการทำงานกับไฟล์
ขั้นตอนการสร้าง
ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่
Android Studio → File → New Project → กรอกรายละเอียด
ขั้นตอนที่ 2: จัดรูปแบบหน้าจอ (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"
tools:context=".MainActivity"
android:orientation="vertical">
<EditText
android:id="@+id/enterText"
android:hint="กรุณาป้อนข้อความที่นี่"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/save"
android:text="บันทึก"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/output"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp" />
</LinearLayout>
ขั้นตอนที่ 3: เขียนโค้ด MainActivity (src/MainActivity.java)
package com.example.andy.myapplication;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
Button save;
ArrayList<String> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView output = findViewById(R.id.output);
final EditText enterText = findViewById(R.id.enterText);
save = findViewById(R.id.save);
save.setOnClickListener(v -> {
String input = enterText.getText().toString().trim();
if (!input.isEmpty()) {
// สร้างโฟลเดอร์ text ใน Internal Storage
File dir = new File(getFilesDir(), "text");
if (!dir.exists()) {
dir.mkdirs();
}
try {
File file = new File(dir, "sample.txt");
FileWriter writer = new FileWriter(file, true); // true = append mode
writer.append(input).append("\n");
writer.flush();
writer.close();
output.setText(readFile());
Toast.makeText(this, "บันทึกข้อความสำเร็จ", Toast.LENGTH_LONG).show();
enterText.setText(""); // ล้างช่องป้อน
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "เกิดข้อผิดพลาด: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
// โหลดข้อมูลเดิมตอนเริ่มต้น
output.setText(readFile());
}
private String readFile() {
File file = new File(getFilesDir(), "text/sample.txt");
StringBuilder text = new StringBuilder();
if (!file.exists()) {
return "ยังไม่มีข้อมูล";
}
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
list.clear();
while ((line = br.readLine()) != null) {
list.add(line);
text.append(line).append("\n");
}
} catch (IOException e) {
e.printStackTrace();
}
return text.length() > 0 ? text.toString() : "ยังไม่มีข้อมูล";
}
}
ขั้นตอนที่ 4: AndroidManifest.xml (Permissions)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.example.andy.myapplication">
<!-- ไม่ต้องการ WRITE_EXTERNAL_STORAGE สำหรับ Internal Storage -->
<!-- แต่ใส่ไว้เผื่อใช้ External Storage ในอนาคต -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
การทดสอบ
รันแอปพลิเคชัน ป้อนข้อความ กดบันทึก หลายครั้ง

ข้อความจะถูกเพิ่มต่อท้าย (Append) และแสดงใน TextView

ตรวจสอบไฟล์ที่: /data/data/<package.name>/files/text/sample.txt

Internal Storage vs External Storage
| คุณสมบัติ | Internal Storage | External Storage |
|---|---|---|
| Path | /data/data/package/files/ | /sdcard/ หรือ /storage/emulated/0/ |
| Permission | ไม่ต้องการ Permission | ต้องการ Permission (API < 29) |
| เข้าถึงโดย App อื่น | ไม่ได้ (Private) | ได้ (Public) |
| ถูกลบเมื่อ Uninstall | ใช่ | ไม่ (ถ้าไม่อยู่ในโฟลเดอร์แอป) |
| พื้นที่ | จำกัด | มากกว่า |
แนวทางปฏิบัติที่ดีกว่า (Modern Android)
1. ใช้ Kotlin Coroutines + Okio
// FileManager.kt
class FileManager @Inject constructor(@ApplicationContext context: Context) {
private val baseDir = File(context.filesDir, "text")
suspend fun appendToFile(fileName: String, text: String) = withContext(Dispatchers.IO) {
baseDir.mkdirs()
File(baseDir, fileName).bufferedWriter().use { it.write(text + "\n") }
}
suspend fun readFile(fileName: String): List<String> = withContext(Dispatchers.IO) {
File(baseDir, fileName).readLines().orEmpty()
}
}
2. ใช้ DataStore (Preferences/Proto) แทน Text File
// สำหรับข้อมูลโครงสร้าง (Structured Data) ใช้ DataStore/Room แทน
@Serializable
data class UserSettings(
val items: List<String> = emptyList()
)
// Proto DataStore สำหรับ List
// ใช้ได้กับข้อมูลที่ซับซ้อนกว่า Text File
3. ใช้ JSON/Gson สำหรับ List ที่ซับซ้อน
// เขียน List เป็น JSON
val gson = Gson()
val json = gson.toJson(myList)
file.writeText(json)
// อ่าน JSON กลับเป็น List
val list = gson.fromJson(file.readText(), object : TypeToken<List<String>>() {}.type)
Best Practices
- ใช้
getFilesDir()สำหรับ Internal Storage (Private, ไม่ต้อง Permission) - ใช้
FileWriter(file, true)สำหรับ Append Mode - ใช้ Try-with-resources (Java 7+) หรือ Kotlin .use() ปิด Resource อัตโนมัติ
- รัน File I/O บน Background Thread (IO Dispatcher) ไม่ใช่ Main Thread
- จัดการ Exception ให้ครบถ้วน
- สำหรับข้อมูลโครงสร้าง ใช้ Room Database หรือ DataStore แทน
สรุป
การเขียน/อ่านไฟล์ Text ใน Internal Storage ใช้งานง่าย เหมาะสำหรับข้อมูลเล็กๆ แบบไม่โครงสร้าง สำหรับข้อมูลที่ซับซ้อน ต้องการ Query หรือ Sync ควรใช้ Room Database หรือ DataStore แทน