การใช้งาน Path Provider และการเชียนอ่าน File ใน Flutter
เขียนเมื่อ 1 ปีก่อน โดย Ninenik Narkdeeflutter path provider file folder
คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ flutter path_provider file folder
ไปที่
Copy


เราได้รู้จักการเก็บข้อมูลแบบถาวรไว้ใน app มาแล้ว
preferences ในรุปแบบข้อมูล key-value เนื้อหานี้จะมาดูเกี่ยว
กับการใช้งานไฟล์ เป็นอีกรูปแบบของการเก็บข้อมูล
*เนื้อหานี้ใช้เนื้อหาต่อเนื่องจากบทความ http://niik.in/960
การใช้งาน Path Provider
เป็น package ที่เราจะจัดการตำแหน่งของข้อมูลไฟล์ใน app หรือก็คือ path ต่างๆ
ของ app ก่อนใช้งานต้องทำการติดตั้งดังนี้
ติดตั้ง path_provider กำหนดในไฟล์ pubspec.yaml
dependencies: path_provider: ^2.0.7
จากนั้น import เข้ามาใช้งานในหน้าที่ต้องการด้วยคำสั่ง
import 'package:path_provider/path_provider.dart';
การทำงานหลักๆ ของ package นี้ก็คือคำสั่งที่จะดึงข้อมูล path ใน app ที่เราต้องการใช้งาน
รองรับทั้งระบบ ios และ android ซึ่งเราจะดูเฉพาะส่วนของ android
การใช้งาน path provider จะรองรับทั้งข้อมูลภายในและภายนอกหรือ Internal /External Storage
ข้อมูลหลักๆ ที่เกี่ยวข้องก็จะเป็น Directory และ File หรือก็คือโฟเดอร์ และ ไฟล์
คำสั่งการทำงานของ path_provider
ดูคำสั่งการทำงานและค่าของข้อมูลที่ได้เมื่อใช้งาน
// ส่วนของ Internal Storage final tempDirectory = await getTemporaryDirectory(); // Directory: '/data/user/0/com.example.flutter_app3/cache' final appSupportDirectory = await getApplicationSupportDirectory(); // Directory: '/data/user/0/com.example.flutter_app3/files' final appDocumentsDirectory = await getApplicationDocumentsDirectory(); // Directory: '/data/user/0/com.example.flutter_app3/app_flutter' // ส่วนของ External Storage final externalDocumentsDirectory = await getExternalStorageDirectory(); // Directory: '/storage/emulated/0/Android/data/com.example.flutter_app3/files' final externalCacheDirectories = await getExternalCacheDirectories(); // [Directory: '/storage/emulated/0/Android/data/com.example.flutter_app3/cache', // Directory: '/storage/1818-160B/Android/data/com.example.flutter_app3/cache'] final externalStorageDirectories = await getExternalStorageDirectories(type: StorageDirectory.music); // [Directory: '/storage/emulated/0/Android/data/com.example.flutter_app3/files/Music', // Directory: '/storage/1818-160B/Android/data/com.example.flutter_app3/files/Music']
ข้อมูล External Storage จะรองรับก็ต่อเมื่อมีการใช้งาน เช่น สมมติเราไม่มีการใช้งาน SD Card หรือ
ที่จัดเก็บข้อมูลภายนอก ก็จะไม่สามารถเรียกดูข้อมูลส่วนนี้ได้ โฟลเดอร์หลักที่เราสามารถเข้าถึงได้ก็คือ
โฟลเดอร์ที่เป็นชื่อ package ของ app ทั้งแบบ internal และ external ในตัวอย่างก็คือโฟลเดอร์ชื่อ com.example.flutter_app3 โดยทั่วไปเราจะไม่ได้สิทธิ์เข้าถึงโฟลเดอร์ที่อยู่เหนือกว่านี้ได้ ข้อมูลชั่วคราว
ที่เกิดขึ้นระหว่างใช้งาน app จะถูกเก็บไว้ในโฟลเดอร์ cache หรือเราเรียกว่า Temporary directory สามารถ
ถูกลบได้ตลอดเวลา ดังนั้นในส่วนนี้จะไม่ใช้เก็บข้อมูลที่สำคัญๆ ไว้
ในทุกๆ flutter app ส่วนใหญ่จะมี Documents directory อยู่ในโฟลเดอร์ชื่อ app_flutter เป็นที่สำหรับ
เก็บไฟล์ที่ตัว app เท่านั้นสามารถเรียกใช้งานได้ ใน android จะเรียกว่า AppData directory ข้อมูลจะลบ
ก็ต่อเมื่อเราทำการลบ app ออกจากเครื่อง
ตัวอย่างโค้ดไฟล์ home.dart ต่อไปนี้ เราจะจำลองแสดงรายการข้อมูลไฟล์ในโฟลเดอร์ package ของ app
ซึ่งปกติแล้ว โครงสร้างข้อมูลพวกนี้ เราจะใช้ app ใช้งานเท่านั้น ไม่ได้นำมาแสดงให้ผู้ใช้ทั่วไปเห็นหรือใช้งาน
แต่ในที่นี้ต้องการนำมาแสดงเป็นแนวทางให้เห็นโครงสร้างไฟล์และโฟลเดอร์ของ app เท่านั้น
ไฟล์ home.dart
import 'dart:io'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:path_provider/path_provider.dart'; import '../components/sidemenu.dart'; class Home extends StatefulWidget { static const routeName = '/'; const Home({Key? key}) : super(key: key); @override State<StatefulWidget> createState() { return _HomeState(); } } class _HomeState extends State<Home> { List<FileSystemEntity?>? _folders; String _currentPath = ''; // เก็บ path ปัจจุบัน Directory? _currentFolder; // เก็บ โฟลเดอร์ที่กำลังใช้งาน @override void initState() { // TODO: implement initState super.initState(); _loadFolder(); } // เปิดโฟลเดอร์ และแสดงรายการในโฟลเดอร์ void _setPath(dir) async { _currentFolder = dir; _currentPath = dir.path; final myDir = Directory(_currentPath); try{ setState(() { _folders = myDir.listSync(recursive: false, followLinks: false); }); }catch(e){ print(e); } } // จำลองสร้างไฟล์ใหม่ void _newFile() async { String newFile = "${_currentFolder!.path}/myfile.txt"; final myfile = File(newFile); // กำหนด file object final isExits = await myfile.exists(); // เช็คว่ามีไฟล์หรือไม่ if(!isExits){ // ถ้ายังไม่มีไฟล์ try{ // สร้างไฟล์ text var file = await myfile.writeAsString( 'Hello World' ); print(file); }catch(e){ print(e); } }else{ // ถ้ามีไฟล์อยู่แล้ว จำลองการลบข้อมูล try{ await myfile.delete(); }catch(e){ print(e); } } // โหลดข้อมูลใหม่อีกครั้ง setState(() { _setPath(_currentFolder!); }); } // คำสั่งจำลองการสร้างโฟลเดอร์ void _newFolder() async { String newFolder = "${_currentFolder!.path}/mydir"; final myDir = Directory(newFolder); // สร้าง directory object var isExits = await myDir.exists(); // เช็คว่ามีแล้วหรือไม่ if(!isExits){ // ถ้ายังไม่มีสร้างโฟลเดอร์ขึ้นมาใหม่ try{ var directory = await Directory(newFolder).create(recursive: true); print(directory); }catch(e){ print(e); } }else{ // ถ้ามีแล้วจำลองการทำคำสั่งลบ try{ await myDir.delete(recursive: true); }catch(e){ print(e); } } // โหลดข้อมูลใหม่อีกครั้ง setState(() { _setPath(_currentFolder!); }); } void _loadFolder() async { // ข้อมูลเกี่ยวกับโฟลเดอร์ Directory ต่างๆ final tempDirectory = await getTemporaryDirectory(); final appSupportDirectory = await getApplicationSupportDirectory(); final appDocumentsDirectory = await getApplicationDocumentsDirectory(); final externalDocumentsDirectory = await getExternalStorageDirectory(); final externalStorageDirectories = await getExternalStorageDirectories(type: StorageDirectory.music); final externalCacheDirectories = await getExternalCacheDirectories(); /* print(tempDirectory); print(appSupportDirectory); print(appDocumentsDirectory); print(externalDocumentsDirectory); print(externalCacheDirectories); print(externalStorageDirectories); */ // เมื่อโหลดขึ้นมา เาจะเปิดโฟลเดอร์ของ package เป้นโฟลเดอร์หลัก _currentFolder = appDocumentsDirectory.parent; _currentPath = appDocumentsDirectory.parent.path; final myDir = Directory(_currentPath); setState(() { _folders = myDir.listSync(recursive: false, followLinks: false); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Home'), actions: <Widget>[ // IconButton( onPressed: _newFolder, // สร้างโฟลเดอร์ใหม่ icon: FaIcon(FontAwesomeIcons.folderPlus), ), IconButton( onPressed: _newFile, // สร้างไฟล์ใหม่ icon: FaIcon(FontAwesomeIcons.fileAlt), ), ], ), body: Column( mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ ListTile( leading: FaIcon(FontAwesomeIcons.angleLeft), title: Text('${_currentPath.replaceAll('/data/user/0/com.example.flutter_app3', '/')}'), onTap: (){ _setPath(_currentFolder!.parent); } ), Expanded( child: _folders!=null // เมื่อไม่ใช่ค่า null ? ListView.separated( // กรณีมีรายการ แสดงปกติ itemCount: _folders==null ? 0 : _folders!.length, itemBuilder: (context, index) { var isFolder = _folders![index] is Directory ? true : false; // เช็คว่าเป็นโฟลเดอร์ var isFile = _folders![index] is File ? true : false; // เช็คว่าเป็นไฟล์ if(_folders![index] != null){ // เอาเฉพาะชื่อหลัง / ตัวสุดท้าย String fileName = _folders![index]!.path.split('/').last; return ListTile( leading: isFolder ? FaIcon(FontAwesomeIcons.solidFolder) : FaIcon(FontAwesomeIcons.file), title: Text('${fileName}'), onTap: (isFolder==true) ? (){ // กรณีเป้นโฟลเดอร์ _setPath(_folders![index]!); // ถ้ากด ให้ทำคำสั่งเปิดโฟลเดอร์ } : (){}, // กรณีเป็นไฟล์ ); }else{ return Container(); } }, separatorBuilder: (BuildContext context, int index) => const Divider(height: 1,), ) : const Center(child: Text('No items')), // กรณีไม่มีรายการ ), ], ), drawer: SideMenu(), ); } }
ตัวอย่างผลลัพธ์และการทำงาน

ในตัวอย่างการทำงาน เราเริ่มต้นที่ package โฟลเดอร์ ในที่นี้คือ com.example.flutter_app3 โดยมี action
icon มุมบนขวาสองรายการคือ สร้างโฟลเดอร์ใหม่ กับ สร้างไฟล์ใหม่ ซึ่งถ้ากดซ้ำก็จะเป็นการลบตัวที่เคยสร้าง
เป็นการจำลองการทำงานสำหรับการลบข้อมูล
ส่วนบนของลิสรายการข้อมูลไฟล์และโฟลเดอร์จะแสดง path ปัจจุบัน จะตัด path ที่อยู่ระดับบนกว่าออก
แสดงเฉพาะ path ต่อจาก package โฟลเดอร์ ถ้ากดที่รายการนี้จะเป็นการย้อนกลับไปโฟลเดอร์ระดับบน
หรือก็คือถอยกลับไปข้างบนหนึ่งระดับ
สำหรับลิสรายการโฟลเดอร์หรือไฟล์ ถ้าเป็นโฟลเดอร์เมื่อกด จะเป็นการเปิดโฟลเดอร์นั้น และตั้งเป็นโฟลเดอร์
ปัจจุบันที่กำลังใช้งาน ถ้าเป็นไฟล์ในที่นี้ยังไม่กำหนดการทำงาน
ตัวอย่างการทำงานทั้งหมดนี้ เราต้องการให้เห็นแนวทาง และวิธีการจัดการเกี่ยวกับไฟล์และโฟลเดอร์ เช่น
สร้างโฟลเดอร์/ไฟล์ใหม่ ใช้งาน และ ลบโฟลเดอร์/ไฟล์ รวมถึงการนำเอา path_provider มาใช้ในการหาตำแหน่ง
ของโฟลเดอร์ต่างๆ ในระบบ android
เนื้อหานี้จะมีรายละเอียดเพิ่มเติมในตอนหน้า เกี่ยวกับการจัดการไฟล์ และอื่นๆ อย่าลืมว่าระบบการจัดการไฟล์นี้
เป็นส่วนของการทำงานของ app ที่เราอาจจะใช้งาน ไม่ใช่ส่วนที่ผู้ใช้ทั่วไปจะสามารถเข้าถึงแบบเต็มรูปแบบ แต่ที่ยก
มาก็เพื่อให้เห็นโครงสร้างและการทำงาน ตัวอย่างการนำไปใช้ ก็เช่น เรามีไฟล์ json บน server ที่อาจจะอัพเดท
ทุกๆ วันหรือวันละครั้ง และเราต้องการให้ผู้ใช้สามารถดูข้อมูลแบบออฟไลน์ได้ ถ้าไม่ได้ต่อเน็ต เราก็ทำการดาวน์โหลด
ไฟล์ json นั้นลงมาบันทึกไว้ที่เครื่อง และกำหนดให้เรียกใช้งานเมื่อออฟไลน์ เป็นต้น
สำหรับเนื้อหาในบทความนี้ เราใช้ส่วนของ app เริ่มต้นจากบทความด้านล่าง ทบทวนได้ที่
การใช้งาน Drawer กำหนด SideMenu ใน Flutter เบื้องต้น http://niik.in/960
https://www.ninenik.com/content.php?arti_id=960 via @ninenik

เนื้อหาตอนหน้าจะเป็นอะไร รอติดตามการประยุกต์ต่อเพิ่มเติมในตอนหน้า
กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ

อ่านต่อที่บทความ
-
04 Dec2021การใช้งาน Dismissible Widget ร่วมกับ ListView ใน Flutter อ่าน 2,891
เนื้อหานี้เรายังอยู่กับการจัดการไฟล์ และโฟลเดอร์ แต่จะมาเสริมการประยุกต์ก
เนื้อหาที่เกี่ยวข้อง
-
05 Nov2021การใช้งาน Provider จัดการข้อมูล App State ใน Flutter อ่าน 8,802
เนื้อหาตอนต่อไปนี้เราจะมาดูเกี่ยวกับการใช้งาน provider จ้ดการข้อมูล app s
-
06 Nov2021จัดการข้อมูลด้วย SQL Database โดยใช้ Sqflite ใน Flutter อ่าน 7,939
เนื้อหาตอนต่อไปนี้จะมาแนะนำ การบันทึกข้อมูลไว้ใน app ในรูปแบบ SQLite data
-
08 Nov2021การใช้งาน Form และ Form Validation ใน Flutter อ่าน 9,307
เนื้อหาตอนต่อไปนี้ เราจะมาดูเกี่ยวกับการใช้งาน form ใน flutter เริ่มตั้งแ
-
10 Nov2021การจัดการข้อมูลของ Form Element อื่นๆ ใน Flutter อ่าน 2,845
เนื้อหาต่อไปนี้ จะมาดูต่อเกี่ยวกับการใช้งานฟอร์ม ต่อจาก เนื้อหาตอนที่แล้ว
-
11 Nov2021ประยุกต์ใช้งาน Form บันทึกลงฐานข้อมูล ใน Flutter อ่าน 2,800
เนื้อหานี้จะเป็นเนื้อหาประยุกต์เพิ่มเติม เล็กน้อยเกี่ยวกับการ ปรับใช้งานฟ
-
22 Nov2021ประยุกต์เก็บข้อมูลด้วย shared preferences ใน Flutter อ่าน 3,781
เนื้อหาตอนต่อไปนี้ เราจะมาประยุกต์การใช้งาน plugin ที่ใช้ สำหรับเก็บข้อมู
-
24 Nov2021ประยุกต์ระบบ Register Login ผ่าน API บน server ใน Flutter อ่าน 6,269
เนื้อหาต่อไปนี้เป็นการประยุกต์ใช้งาน ต่อเนื้อง จากเนื้อหาตอนที่แล้ว เกี่ย
-
25 Nov2021ใช้งาน Firebase Authentication จัดการระบบสมาชิกใน Flutter อ่าน 2,148
สำหรับเนื้อหานี้จะเป็นแนวทางการประยุกต์อีกรูปแบบ ของระบบสมาชิก ที่เราไม่จ
-
26 Nov2021ประยุกต์ระบบ Register Login ด้วย Firebase Auth ใน Flutter อ่าน 4,778
ต่อเนื่องจากบทความตอนที่แล้ว ที่เราได้เตรียมพร้อมและ ตั้งค่าส่วนต่างๆ สำห
-
27 Nov2021การเปลี่ยนชื่อ App ชื่อ Package และไอคอน ใน Flutter อ่าน 4,369
เนื้อหาตอนต่อไปนี้จะมาแนะนำวิธีการเปลี่ยนชื่อ app และ ไอคอนของ app
-
28 Nov2021การกำหนด Splash screen ให้กับ app ใน Flutter อ่าน 3,915
Splash screen หรือที่รู้จักใช้ชื่อ Launch screens เป็น ส่วนที่ทำงานเริ่มต
-
29 Nov2021การสร้าง Keystore และการ Build app ใน Flutter อ่าน 5,906
เนื้อหาตอนต่อไปนี้จะมาดูวิธีการสร้าง keystore สำหรับใช้ ในการ build app เ
-
กำลังอ่านเนื้อหานี้อยู่03 Dec2021การใช้งาน Path Provider และการเชียนอ่าน File ใน Flutter อ่าน 4,159
เราได้รู้จักการเก็บข้อมูลแบบถาวรไว้ใน app มาแล้ว ไม่ว่าจะเป็นการใช้งาน ฐา
-
04 Dec2021การใช้งาน Dismissible Widget ร่วมกับ ListView ใน Flutter อ่าน 2,891
เนื้อหานี้เรายังอยู่กับการจัดการไฟล์ และโฟลเดอร์ แต่จะมาเสริมการประยุกต์ก
URL สำหรับอ้างอิง
Top
Copy
ขอบคุณทุกการสนับสนุน
![]()