Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีสร้างไฟล์ Text ใน Internal Storage บน Android

ภาพรวม

ตัวอย่างนี้สาธิตการสร้างและเขียนไฟล์ Text (.txt) ลงใน Internal Storage ของแอปพลิเคชัน Android ไฟล์จะถูกเก็บที่ /data/data/<package.name>/files/text/sample.txt ซึ่งเป็นพื้นที่ส่วนตัวของแอป (Private) ไม่ต้องการ Permission และจะถูกลบเมื่อ Uninstall แอป

ขั้นตอนการสร้าง

ขั้นตอนที่ 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" />

</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.Toast;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
    Button save;

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

        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()) {
                    boolean created = dir.mkdirs();
                    if (!created) {
                        Toast.makeText(this, "สร้างโฟลเดอร์ไม่สำเร็จ", Toast.LENGTH_SHORT).show();
                        return;
                    }
                }

                try {
                    File file = new File(dir, "sample.txt");
                    // true = append mode (เพิ่มต่อท้าย), false = overwrite (ทับ)
                    FileWriter writer = new FileWriter(file, true);
                    writer.append(input).append("\n");
                    writer.flush();
                    writer.close();
                    
                    Toast.makeText(this, "บันทึกข้อความสำเร็จ", Toast.LENGTH_LONG).show();
                    enterText.setText("");
                } catch (IOException e) {
                    e.printStackTrace();
                    Toast.makeText(this, "เกิดข้อผิดพลาด: " + e.getMessage(), Toast.LENGTH_LONG).show();
                }
            } else {
                enterText.setError("กรุณาป้อนข้อความ");
            }
        });
    }
}

ขั้นตอนที่ 4: AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="com.example.andy.myapplication">

    <!-- Internal Storage ไม่ต้องการ Permission -->
    <!-- Permission นี้สำหรับ External Storage (API < 29) -->
    <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>

การทดสอบ

รันแอปพลิเคชัน ป้อนข้อความ กดบันทึก

วิธีสร้างไฟล์ Text ใน Internal Storage บน Android

ข้อความถูกบันทึกสำเร็จ

วิธีสร้างไฟล์ Text ใน Internal Storage บน Android

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

วิธีสร้างไฟล์ Text ใน Internal Storage บน Android

Internal Storage Paths

// ไดเรกทอรีหลักของแอป (Private)
context.filesDir                    // /data/data/package/files/
context.cacheDir                    // /data/data/package/cache/ (อาจถูกลบโดยระบบ)

// ไดเรกทอรีเฉพาะประเภท
context.getDir("custom", MODE_PRIVATE)  // /data/data/package/app_custom/

// Database
context.getDatabasePath("mydb.db")      // /data/data/package/databases/mydb.db

// SharedPreferences
context.getSharedPreferences("prefs", MODE_PRIVATE) // /data/data/package/shared_prefs/prefs.xml

Mode การเปิดไฟล์ (FileWriter Constructor)

// Overwrite (ทับไฟล์เดิม) - Default
new FileWriter(file)
new FileWriter(file, false)

// Append (เพิ่มต่อท้ายไฟล์เดิม)
new FileWriter(file, true)

แนวทางปฏิบัติที่ดีกว่า (Modern Android)

1. ใช้ Kotlin Extension Functions

// File Extensions
fun File.writeText(text: String, append: Boolean = false) {
    bufferedWriter(append).use { it.write(text) }
}

fun File.readText(): String = bufferedReader().use { it.readText() }

fun File.readLines(): List<String> = bufferedReader().use { it.readLines() }

// Usage
val file = File(context.filesDir, "text/sample.txt")
file.writeText("Hello\n", true)  // Append
val content = file.readText()
val lines = file.readLines()

2. ใช้ Coroutines สำหรับ I/O Operations

// Repository Class
class FileRepository @Inject constructor(@ApplicationContext context: Context) {
    private val baseDir = File(context.filesDir, "text").apply { mkdirs() }
    
    suspend fun appendText(fileName: String, text: String) = withContext(Dispatchers.IO) {
        File(baseDir, fileName).writeText(text + "\n", true)
    }
    
    suspend fun readAllText(fileName: String): String = withContext(Dispatchers.IO) {
        File(baseDir, fileName).readText()
    }
    
    suspend fun readLines(fileName: String): List<String> = withContext(Dispatchers.IO) {
        File(baseDir, fileName).readLines()
    }
}

3. ใช้ Okio Library (Square)

// build.gradle
implementation "com.squareup.okio:okio:3.9.0"

// Usage
val sink = Okio.buffer(Okio.sink(file))
sink.writeUtf8("Hello").writeUtf8("\n")
sink.close()

val source = Okio.buffer(Okio.source(file))
val text = source.readUtf8()
source.close()

เมื่อไหร่ควรใช้ Internal Storage Text File

เหมาะสำหรับ ไม่เหมาะสำหรับ
Log/Debug Files ข้อมูลโครงสร้างที่ต้อง Query/Filter
Cache ชั่วคราว ข้อมูลขนาดใหญ่ (ใช้ Database)
Config เรียบง่าย ข้อมูลที่ต้อง Sync/Backup
Export/Import ไฟล์เล็ก Concurrent Read/Write หลาย Thread

Best Practices

  • ใช้ getFilesDir() สำหรับไฟล์ถาวร, getCacheDir() สำหรับไฟล์ชั่วคราว
  • รัน I/O บน Background Thread (Dispatcher.IO / Executor)
  • ใช้ Try-with-resources / .use() ปิด Stream อัตโนมัติ
  • จัดการ Exception และ Disk Space Full
  • ตั้งชื่อไฟล์/โฟลเดอร์เป็นภาษาอังกฤษ ไม่มี Space
  • สำหรับข้อมูลโครงสร้าง: ใช้ Room Database, DataStore, หรือ JSON + File

สรุป

การเขียนไฟล์ Text ใน Internal Storage ใช้งานง่าย เหมาะสำหรับข้อมูลเล็กๆ แบบ Sequential Access ไม่ต้องการ Permission และปลอดภัย (Private) สำหรับข้อมูลที่ซับซ้อนกว่านี้ ควรพิจารณา Room Database หรือ DataStore