ในการเขียน native แอป เพื่ออ่าน File และ Directory จากเครื่องที่แอปทำงานอยู่ สามารถใช้งานผ่าน dart:io การใช้งานจะต้องประกาศ import 'dart:io';
เพื่อให้สามารถเรียกใช้งาน class File
Directory
Link
สำหรับเข้าถึงไฟล์ในดิสก์หรือ network ได้ โดยตัว API จะรองรับทั้งแบบ synchronous และ asynchronous โดยสังเกตได้จากคำสั่งที่ลงท้ายด้วย *Sync จะเป็นการทำงานแบบ synchronous
class File
Directory
Link
ต่าง implement FileSystemEntity
class ซึี่งเป็น abstract class จะมีคำสั่งที่ช่วยในการจัดการ File และ Directory ที่เหมือนกัน และยังมี static method ช่วยในการทำงานอีกด้วย
FileSystemEntity class
.parent
ไม่ว่าจะเป็น File หรือ Directory จะต้องบรรจุอยู่ใน Directory ที่เป็น parent อีกที หากต้องการใช้งานสามารถใช้คำสั่ง .parent
เพื่อคืนค่ากลับมาเป็น Directory
Link
class ในกรณีที่ตัว entity ที่อ้างอิงอยู่ใน root directory ทำให้ parent คืนค่ากับมาเป็น root directory
import 'dart:io';
void main() {
File iniFile = File(r'C:\Windows\win.ini');
Directory parent = iniFile.parent;
print(parent); // output → Directory: 'C:\Windows'
Directory c = Directory(r'C:\'); // root directory
print(c.parent); // output → Directory: 'C:\'
}
อีกวิธีโดยการใช้ static method .parentOf()
ของ FileSystemEntity โดยจะคืนมาเป็น String ที่เป็นตัว parent ของ path ที่ต้องการ
import 'dart:io';
void main() {
String parent;
parent = FileSystemEntity.parentOf(r'C:\Windows\win.ini');
print(parent); // output → C:\Windows
parent = FileSystemEntity.parentOf(r'C:\Windows\.');
print(parent); // output → C:\Windows
parent = FileSystemEntity.parentOf(r'C:\Windows\');
print(parent); // output → C:\
parent = FileSystemEntity.parentOf(r'C:\');
print(parent); // output → C:\
parent = FileSystemEntity.parentOf(r'\\server1\folder1\.');
print(parent); // output → \\server1\folder1
parent = FileSystemEntity.parentOf(r'\\server1\folder1\');
print(parent); // output → \\server1
parent = FileSystemEntity.parentOf(r'\\server1\folder1');
print(parent); // output → \\server1
}
เนื่องจากในการอ้างถึงตำแหน่งของ entity สามารถระบุได้ทั้งแบบ absolute หรือ relative ก็ได้ โดยใช้คำสั่ง .path
คืนค่ามาเป็นข้อความของ path ที่ใช้สร้าง entity ดังนั้นในกรณีที่อ่านค่า path ของ entity อาจได้แบบ relative มา หากต้องการค่าของ path แบบ absolute ต้องใช้คำสั่ง .absolute
โดยจะคืนค่ากลับมาเป็น entity แบบเดียวกัน
import 'dart:io';
void main() {
File iniFile = File(r'C:\Windows\win.ini');
Directory parent = iniFile.parent;
print(iniFile.path); // output → c:\Windows\win.ini
print(parent.path); // output → c:\Windows
File someFile = File(r'dart_file.dart');
File fullPath = someFile.absolute;
print(someFile.path); // output → dart_file.dart
print(fullPath.path); // output → C:\src\dart\dart_tester\dart_file.dart
Directory currentPath = Directory('.');
Directory currentAbsolute = currentPath.absolute;
print(currentPath.path); // output → .
print(currentAbsolute.path); // output → c:\src\dart\dart_tester\
Directory currentAbsolute2 = Directory('.').absolute;
print(currentAbsolute2.path); // output → c:\src\dart\dart_tester\
}
หากต้องการตรวจสอบว่า ตัวข้อความที่ใช้สร้าง entity เป็นการอ้างอิงแบบ absolute หรือไม่ สามารถใช้คำสั่ง .isAbsolute
ตรวจสอบได้
import 'dart:io';
void main() {
File iniFile = File(r'C:\Windows\win.ini');
File someFile = File(r'dart_file.dart');
print(iniFile.isAbsolute); // output → true
print(someFile.isAbsolute); // output → false
}
เมื่อระบุข้อความที่เป็นตำแหน่ง path ของ File Directory หรือ Link ในกรณีที่ต้องการระบุถึง entity ที่มีอยู่แล้ว ไม่ใช่ต้องการสร้างใหม่ ก่อนการเข้าถึงจำเป็นต้องทำการตรวจสอบก่อนว่า entity มีอยู่จริงหรือไม่ ด้วยคำสั่ง .exists()
และ .existsSync()
หากไม่ตรวจสอบก่อนว่ามีอยู่หรือไม่ จะเกิด error ขึ้นได้เมื่อทำการอ่านข้อมูลจาก entity ดังกล่าว
import 'dart:io';
void main() {
File someFile = File(r'C:\Windows\win.ini');
if (someFile.existsSync()) {
print(someFile.lastModifiedSync()); // output → 2019-12-07 16:12:42.000
} else {
print("${someFile.path} not found.");
}
// try to get information from non-existent file
File newFile = File(r'C:\newfile.txt'); // no file on disk
print(newFile.lastModified()); // PathNotFoundException: Cannot retrieve modification time
}
เมื่อใช้คำสั่งจำพวกอ่านข้อมูล entity จาก Directory เช่น คำสั่ง .list()
หรือ .listSync()
ผลที่ได้จากคำสั่งจะเป็น List ของ FileSystemEntity ดังนั้น หากต้องการจะเลือกเฉพาะ File หรือ Directory อย่างใดอย่างหนึ่ง สามารถใช้คำสั่งต่อไปนี้เพื่อตรวจสอบ path ของ FileSystemEntity ได้
.isFile()
.isFileSync()
สำหรับตรวจสอบว่าเป็น File หรือไม่.isDirectory()
.isDirectoryeSync()
สำหรับตรวจสอบว่าเป็น Directory หรือไม่.isLink()
.isLinkSync()
สำหรับตรวจสอบว่าเป็น Link หรือไม่import 'dart:io';
void main() {
// test exists file with absolute path
File file1 = File(r'C:\Windows\win.ini');
print(FileSystemEntity.isFileSync(file1.path)); // output → true
// test exists file with relative path
File file2 = File(r'README.md');
print(FileSystemEntity.isFileSync(file2.path)); // output → true
// test for non-existent file
File file3 = File(r'C:\no_file.xxx');
print(FileSystemEntity.isFileSync(file3.path)); // output → false
// test path of directory
print(FileSystemEntity.isFileSync(r'C:\Windows')); // output → false
// don't use [is] operator to test entity like this
File windows = File(r'C:\Windows');
print(windows is File); // output → true
}
อีกตัวอย่าง ในกรณีที่คำสั่ง .list()
และ .listSync()
ของ Directory class จะคืนค่ามาเป็น List<FileSystemEntity>
โดยเมื่อลองพิมพ์ค่าใน List ที่ได้คืนมาจะพบว่ามันเป็น File class และ Directory class ตามประเภท entity จึงสามารถใช้ is
เพื่อทดสอบว่าเป็น File หรือ Directory ได้ หรือจะเอา .path ของ entity ใน List มาทดสอบด้วย .isFile()
.isFileSync()
.isDirectory()
.isDirectoryeSync()
.isLink()
.isLinkSync()
ก็ได้เช่นเดียวกัน
import 'dart:io';
void main() {
// list file and directory in current directory
List<FileSystemEntity> results = Directory.current.listSync();
print(results); /* output →
[
Directory: 'C:\src\dart\dart_tester\.dart_tool',
File: 'C:\src\dart\dart_tester\.gitignore',
File: 'C:\src\dart\dart_tester\analysis_options.yaml',
Directory: 'C:\src\dart\dart_tester\bin'
]
*/
// It OK to test an entity in List with [is] operator
for (FileSystemEntity f in results) {
if (f is File) {
print("$f is File");
} else if (f is Directory) {
print("$f is Directory");
}
}
}
อีกวิธีที่ใช้ตรวจสอบประเภทของ entity คือคำสั่ง .type()
และ .typeSync()
โดยจะคืนค่ามาเป็น FileSystemEntityType ในตัวอย่างด้านล่างจะเป็นการตรวจสอบว่า path ที่ระบุเป็น entity ประเภทใด
import 'dart:io';
void main() {
String unknowPath = r'./point/to/path/file/link';
switch (FileSystemEntity.typeSync(unknowPath)) {
case FileSystemEntityType.directory:
print('$unknowPath is directory');
break;
case FileSystemEntityType.file:
print('$unknowPath is file');
break;
case FileSystemEntityType.link:
print('$unknowPath is link');
break;
case FileSystemEntityType.notFound:
print('$unknowPath is not found'); // output → ./point/to/path/file/link is not found
break;
default:
print('$unknowPath is something wrong');
}
}
.rename()
.renameSync()
ทั้ง File และ Directory สามารถเปลี่ยนชื่อได้จากคำสั่ง .rename()
และ .renameSync()
โดยกำหนดชื่อใหม่ที่ต้องการ โดยหากไม่สามารถเปลี่ยนชื่อได้ จะเกิด exception
ตัวอย่างการเปลี่ยนชื่อแบบ relative หากไม่ระบุ path ใหม่ ระบุแค่ชื่ออย่างเดียว จะเปลี่ยนชื่อโดยยังอยู่ใน Directory เดิม
import 'dart:io';
void main() {
try {
File textFile = File('test.txt');
File renameFile = textFile.renameSync('test1.txt');
print(renameFile); // output → File: 'test1.txt'
} catch (e) {
print('Error: $e');
}
}
ในกรณีที่ entity ระบุแบบ absolute path แต่ต้องการเปลี่ยนแค่ชื่อ entity ไม่ต้องการเปลี่ยน path สามารถทำได้ดังนี้
import 'dart:io';
void main() {
try {
File textFile = File(r'C:\src\dart\dart_tester\test.txt');
File renameFile = textFile.renameSync('test1.txt');
print(renameFile); // output → File: 'test1.txt'
print(renameFile.absolute); // output → File: 'C:\src\dart\dart_tester\test1.txt'
} catch (e) {
print('Error: $e');
}
}
หากต้องการย้าย entity ไปอยู่ตำแหน่ง path ใหม่ สามารถระบุได้ทั้งแบบ absolute หรือ relative ก็ได้เช่นกัน
import 'dart:io';
void main() {
try {
File textFile = File(r'C:\src\dart\dart_tester\test.txt');
File renameFile = textFile.renameSync(r'test\test.txt'); // move to sub directory
print(renameFile); // output → File: 'test\test.txt'
print(renameFile.absolute); // output → File: 'C:\src\dart\dart_tester\test\test.txt'
} catch (e) {
print('Error: $e');
}
}
ตัว File
class จะมีคำสั่งในการช่วยจัดการ file บนดิสก์หรือเซิร์ฟเวอร์ ตั้งแต่ การสร้างไฟล์ การอ่านไฟล์ คัดลอก ลบ ฯลฯ
ในการสร้างไฟล์ใหม่ สามารถทำได้โดยการสร้าง File object ขึ้นมา โดยระบุชื่อไฟล์ที่ต้องการจะสร้าง จากนั้นให้ทำการเปิดไฟล์ เพื่อทำการเขียนข้อมูลลงไป
.create()
.createSync()
สร้างไฟล์ใหม่ตาม path ที่ระบุ โดยขนาดไฟล์จะเป็น 0 แต่ในกรณีที่ไฟล์ที่ระบุมีอยู่แล้ว จะไม่ทำอะไร.writeAsString()
.writeAsStringSync()
ถ้าไม่มีไฟล์ จะสร้างไฟล์ใหม่ บันทึกข้อความ String ลงในไฟล์โดยตรง.writeAsBytes()
.writeAsBytesSync()
ถ้าไม่มีไฟล์ จะสร้างไฟล์ใหม่ บันทึกข้อมูลที่เป็น List<int>
ลงในไฟล์โดยตรง โดยสมาชิกที่อยู่ใน List จะมีค่าตั้งแต่ 0-255 ถ้ามากกว่านี้จะถูกแปลงให้ไม่เกิน 255.open()
.openSync()
เปิดไฟล์เพื่อทำการบันทึกข้อมูล ผ่าน RandomAccessFile
class.openWrite()
เปิดไฟล์เพื่อทำการบันทึกข้อมูล ผ่าน IOSink
classตัวอย่างการใช้งานคำสั่ง .createSync()
โดยหากถูกสร้างไฟแล้ว และเรียกทำคำสั่งซ้ำ คำสั่งจะไม่ทำอะไรกับไฟล์
import 'dart:io';
void main() {
File testFile = File('test.txt');
testFile.createSync(); // create new file if not exist
print(testFile.lengthSync()); // output → 0
testFile.writeAsStringSync('1234');
print(testFile.lengthSync()); // output → 4
testFile.createSync(); // file was created, do nothing
print(testFile.lengthSync()); // output → 4
}
ตัวอย่างการสร้างไฟล์ โดยระบุข้อมูลที่จะเขียนลงไปด้วย ในกรณีที่มีไฟล์อยู่แล้ว จะเป็นการเขียนทับไฟล์เดิม
import 'dart:io';
void main() {
File testFile = File('test.txt');
// create empty file
testFile.writeAsBytesSync([]);
print(testFile.lengthSync()); // output → 0
// create with text data
testFile.writeAsStringSync('test data');
print(testFile.lengthSync()); // output → 9
print(testFile.readAsStringSync()); // output → test data
// create with binary data
testFile.writeAsBytesSync([100, 120, 150, 65535]);
print(testFile.lengthSync()); // output → 4
print(testFile.readAsBytesSync()); // output → [100, 120, 150, 255]
}
.delete()
.deleteSync()
ใช้คำสั่ง .delete()
.deleteSync()
เพื่อลบไฟล์ที่ระบุ หากไฟล์ไม่มีอยู่หากสั่งลบจะเกิด PathNotFoundException error
ตัวอย่างการสร้างไฟล์ใหม่ จากนั้นลบทิ้ง และลองพยายามลบไฟล์ที่ไม่มีอยู่แล้ว เพื่อให้เกิด error
import 'dart:io';
void main() {
File testFile = File('test.txt');
print(testFile.existsSync()); // output → false
testFile.createSync();
print(testFile.existsSync()); // output → true
testFile.deleteSync();
print(testFile.existsSync()); // output → false
// try to delete non-existent file
testFile.deleteSync(); // PathNotFoundException: Cannot delete file, path = 'test.txt'
}
.copy()
.copySync()
คำสั่ง .copy()
.copySync()
จะทำงานเหมือนกับ .rename()
และ .renameSync()
สิ่งที่แตกต่างกันคือ ไฟล์ต้นฉบับจะยังอยู่
import 'dart:io';
void main() {
File testFile = File('test.txt');
testFile.createSync();
print(testFile.existsSync()); // output → true
File testFile2 = testFile.copySync('test2.txt');
print(testFile.existsSync()); // output → true
print(testFile2.existsSync()); // output → true
}
.readAsBytes()
.readAsBytesSync()
อ่านข้อมูลแบบ binary คืนกลับมาเป็น List<int>
โดยค่าใน List จะอยู่ในช่วง 0-255.readAsString()
.readAsStringSync()
อ่านข้อมูลแบบข้อความ String โดยสามารถระบุ Encoding
ของตัวข้อความว่าเป็นแบบใด ค่าปริยายคือ utf8
.readAsLines()
.readAsLinesSync()
อ่านข้อมูลแบบข้อความ String แต่ทำการแยกข้อมูลเป็นบรรทัดกลับมาในรูปของ List<String>
import 'dart:convert';
import 'dart:io';
void main() {
File testFile = File('test.txt');
// write and read simple text data
testFile.writeAsStringSync('12345678');
print(testFile.lengthSync()); // output → 8
print(testFile.readAsStringSync()); // output → 12345678
// write and read multi-line text
testFile.writeAsStringSync('Line1\nLine2\nLine3');
print(testFile.lengthSync()); // output → 17
print(testFile.readAsLinesSync()); // output → [Line1, Line2, Line3]
// write and read binary data
testFile.writeAsBytesSync([1, 2, 3, 4]);
print(testFile.lengthSync()); // output → 4
print(testFile.readAsBytesSync()); // output → [1, 2, 3, 4]
// write and read UTF-8 encode
testFile.writeAsStringSync("ÀÁÂÃ", encoding: utf8);
print(testFile.lengthSync()); // output → 8
print(testFile.readAsStringSync(encoding: utf8)); // output → ÀÁÂÃ
// write and read ISO Latin-1 encode
testFile.writeAsStringSync("ÀÁÂÃ", encoding: latin1);
print(testFile.lengthSync()); // output → 4
print(testFile.readAsStringSync(encoding: latin1)); // output → ÀÁÂÃ
}
.lastAccessed()
.lastAccessedSync()
วันที่ file ถูกเข้าถึงล่าสุด.lastModified()
.lastModifiedSync()
วันที่ file ถูกแก้ไขล่าสุด.length()
.lengthSync()
ขนาดของ file ในหน่วย byte
คำสั่งข้างต้น หากการอ่านค่าล้มเหลว จะเกิด FileSystemException error.setLastAccessed()
.setLastAccessedSync()
แก้ไขวันที่เข้าถึง file.setLastModified()
.setLastModifiedSync()
แก้ไขวันที่แก้ไขล่าสุดของ fileคำสั่งข้างต้น หากการแก้ไขล้มเหลมจะเกิด FileSystemException error
Directory
class ใช้สำหรับสร้างและจัดการ directory ในดิสก์และเซิร์ฟเวอร์ ตัว API จะมีความคล้ายคลึงกับ File class แต่มีข้อจำกัดที่ไม่เหมือนกัน เช่น ไม่สามารถสั่ง copy ได้โดยตรง จากข้อจำกัดของระบบ File system ในแต่ละ OS ที่แตกต่างกัน
.create()
.createSync()
คำสั่ง .create()
.createSync()
ใช้สำหรับสร้าง directory ใหม่ โดยสามารถกำหนดค่า recursive
ค่าปริยายเป็น false
หากกำหนดเป็นค่า true
จะทำการสร้าง sub directory ให้อัตโนมัต ในกรณีที่ directory นั้นมีอยู่แล้ว จะไม่ทำอะไร
import 'dart:io';
void main() {
print(FileSystemEntity.isDirectorySync(r'.\test')); // output → true
print(FileSystemEntity.isDirectorySync(r'.\test\sub1')); // output → false
// try to create sub directory sub1\sub2 in .\test
Directory subDir = Directory(r'.\test\sub1\sub2');
subDir.createSync(recursive: true);
print(FileSystemEntity.isDirectorySync(r'.\test\sub1')); // output → true
print(FileSystemEntity.isDirectorySync(r'.\test\sub1\sub2')); // output → true
}
คำสั่ง .createTemp()
.createTempSync()
จะเป็นการ directory สำหรับใช้งานชั่วคราวขึ้นมา โดยผู้ใช้สามารถระบุ prefix เพื่อนำไปใช้ในการสร้างได้ ตัว API จะทำการสุ่มตัวอักษรต่อท้าย เพื่อให้ไม่ซ้ำกับ directory อื่น ๆ หากไม่ระบุ prefix จะใช้ empty string เป็น prefix
หากต้องการสร้าง directory ชั่วคราวใน system temp directory สามารถค่าคงที่ Directory.systemTemp
เพื่อใช้งาน Directory ของ Temp ระบบปฏิบัติการได้
import 'dart:io';
void main() {
// This is the system temp directory. ( same as %temp% )
print(Directory.systemTemp.path); // output → C:\Users\chari\AppData\Local\Temp
// create temp directory inside system temp
Directory temp = Directory.systemTemp.createTempSync('_test_temp_');
print(temp); // output → Directory: 'C:\Users\chari\AppData\Local\Temp\_test_temp_78b5195b'
// create temp directory with out prefix
temp = Directory.systemTemp.createTempSync();
print(temp); // output → Directory: 'C:\Users\chari\AppData\Local\Temp\f31e5a31'
}
คำสั่ง .delete()
.deleteSync()
ใช้สำหรับลบ directory ที่ต้องการ โดยสามารถกำหนดค่า
recursive
ค่าปริยายเป็น false
โดย directory ที่จะลบต้องเป็น empty directory คือห้ามมีไฟล์หรือ sub directory ใด ๆtrue
จะทำการลบ sub directory และ file ต่าง ๆ ที่อยู่ภายในให้อัตโนมัตในกรณีที่ล้มเหลวจะเกิด FileSystemException error กลับมา
ตัวอย่าง จะเป็นการลองพยายามลบ directory ที่ภายในมีไฟล์หรือ sub directory หากไม่กำหนด recursive = true
จะเกิด error
import 'dart:io';
void main() {
Directory test;
// Example 1 ------------------------------------------------
// create directory [sub1\sub2] in [.\test]
test = Directory(r'.\test\sub1\sub2');
test.createSync(recursive: true);
// delete directory [sub1] with out recursive
Directory sub1 = Directory(r'.\test\sub1');
try {
sub1.deleteSync(recursive: false);
print('OK');
} catch (e) {
print(e); // output → FileSystemException: Deletion failed, path = '.\test\sub1'
}
// delete directory sub1 with recursive
try {
sub1.deleteSync(recursive: true);
print('OK'); // output → OK
} catch (e) {
print(e);
}
// Example 2 ------------------------------------------------
// create directory [sub1] in [.\test]
test = Directory(r'.\test\sub1');
test.createSync();
// create text file in [sub1]
File(r'.\test\sub1\somefile.txt').createSync();
// delete directory [sub1] with out recursive
try {
sub1.deleteSync(recursive: false);
print('OK');
} catch (e) {
print(e); // output → FileSystemException: Deletion failed, path = '.\test\sub1'
}
// delete directory sub1 with recursive
try {
sub1.deleteSync(recursive: true);
print('OK'); // output → OK
} catch (e) {
print(e);
}
}
.list()
.listSync()
คำสั่ง .list()
.listSync()
จะไล่อ่านว่าใน directory ที่ระบุบรรจุ file และ directory อะไรบ้าง ผลที่ได้จะเป็น List<FileSystemEntity>
List<FileSystemEntity> listSync({
bool recursive = false,
bool followLinks = true,
})
การใช้งาน recursive = true
หาก directory ที่ระบุว่าจะเข้าไปไล่ดูข้อมูล file ภายในมี file และ sub directory จำนวนมาก ควรใช้คำสั่ง .list()
เพื่อให้ประสิทธิภาพการทำงานของแอปเป็นไปอย่างราบรื่น และไม่หยุดตอบสนองกับผู้ใช้
import 'dart:io';
void main() {
// list file and directory in current directory
List<FileSystemEntity> results = Directory.current.listSync();
print(results);
// [recursive = true] for scan all sub directory and files
Future<List<FileSystemEntity>> resultBackground = Directory.current.list(recursive: true).toList();
resultBackground.then((value) => print(value));
print('wait for list of ${Directory.current}');
}
ผลที่ได้
[Directory: 'C:\src\dart\dart_tester.dart_tool', File: 'C:\src\dart\dart_tester.gitignore', File: 'C:\src\dart\dart_tester\analysis_options.yaml', Directory: 'C:\src\dart\dart_tester\bin', File: 'C:\src\dart\dart_tester\CHANGELOG.md', Directory: 'C:\src\dart\dart_tester\lib', File: 'C:\src\dart\dart_tester\pubspec.lock', File: 'C:\src\dart\dart_tester\pubspec.yaml', File: 'C:\src\dart\dart_tester\README.md', Directory: 'C:\src\dart\dart_tester\test', File: 'C:\src\dart\dart_tester\test.txt']
wait for list of Directory: 'C:\src\dart\dart_tester'
[Directory: 'C:\src\dart\dart_tester.dart_tool', File: 'C:\src\dart\dart_tester.dart_tool\package_config.json', File: 'C:\src\dart\dart_tester.gitignore', File: 'C:\src\dart\dart_tester\analysis_options.yaml', Directory: 'C:\src\dart\dart_tester\bin', File: 'C:\src\dart\dart_tester\bin\dart_duration.dart', File: 'C:\src\dart\dart_tester\bin\dart_enum.dart', File: 'C:\src\dart\dart_tester\bin\dart_file.dart', File: 'C:\src\dart\dart_tester\bin\dart_function.dart', File: 'C:\src\dart\dart_tester\bin\dart_regexp.dart', File: 'C:\src\dart\dart_tester\bin\dart_tester.dart', File: 'C:\src\dart\dart_tester\bin\dart_uri.dart', File: 'C:\src\dart\dart_tester\CHANGELOG.md', Directory: 'C:\src\dart\dart_tester\lib', File: 'C:\src\dart\dart_tester\lib\dart_tester.dart', File: 'C:\src\dart\dart_tester\pubspec.lock', File: 'C:\src\dart\dart_tester\pubspec.yaml', File: 'C:\src\dart\dart_tester\README.md', Directory: 'C:\src\dart\dart_tester\test', File: 'C:\src\dart\dart_tester\test.txt']
Exited.
คำสั่ง .current
จะคืนค่าเป็น Directory ที่กำลังทำงานอยู่ เพื่อใช้อ้างกับการระบุ path ที่เป็นแบบ relative
current directory ไม่จำเป็นต้องเป็น directory ที่ไฟล์ executable ของแอปอยู่เสมอไป เพราะในกรณีที่สร้าง shortcut เพื่อเรียกใช้แอป อาจระบุเป็น directory อื่นได้
import 'dart:io';
void main() {
print(Directory.current); // output → Directory: 'C:\src\dart\dart_tester'
}
Link class เป็นการสร้าง Symbolic Link ถ้าใน Windows คือการใช้คำสั่ง mklink
จากที่ลองทดสอบดู พบว่าหากไม่ได้ให้สิทธิ์ Administrator กับแอป จะไม่สามารถสร้างได้ และเกิด FileSystemException error
ตัวอย่างการสร้าง Link เทียบกับคำสั่ง mklink /D E:\sub1\source E:\source
import 'dart:io';
void main() {
// cmd>mklink /D E:\sub1\source E:\source
try {
Link source = Link(r'E:\sub1\source');
source.createSync(r'E:\source');
print('Link created.');
} catch (e) {
print(e);
}
}