รับทําเว็บไซต์ รับทําseo
 
รับทําเว็บไซต์ รับทําseo
บทความที่น่าสนใจ

บทความ ที่น่าสนใจ

Objective-C : File , Folder and data (ตอนที่1)

    File , Folder and data

    ไฟล์เป็นส่วนสำคัญของโปรแกรม แทบจะทุกโปรแกรมต้องเกี่ยวข้องกับการอ่านหรือเขียนข้อมูลจากไฟล์  ในบทนี้เราจะได้เรียนรู้เกี่ยวกับการจัดการไฟล์และไดเรกทอรีหรือโฟลเดอร์ ด้วย Foundation Framework ยกตัวอย่างเช่น การสร้างไฟล์ใหม่ การอ่านไฟล์ การเปลี่ยนชื่อไฟล์ เป็นต้น

     

    File System Layout

    เราควรจะทำความเข้าใจเบื้องต้นเกี่ยวกับโครงสร้างการจัดการไฟล์ก่อนที่จะ ไปใช้คลาสต่างๆที่เกี่ยวไฟล์ ในระบบ Mac OS X นั้น โครงสร้างของระบบไฟล์จะใช้ระบบการเช่นเดียวกันกับระบบปฎิบัติการที่มีพื้น ฐานมาจาก Unix เช่น Free BSD หรือ Linux นั่นคือ มีลักษณะเหมือนรากของต้นไม้

     

    โดยแบ่งออกเป็น 2 ส่วนใหญ่ๆด้วยกัน ส่วนแรก System Files คือไฟล์ของระบบปฎิบัติการ ในส่วนนี้ผู้ใช้งานทั่วๆไปไม่สามารถเข้าไปแก้ไขจัดการได้ ส่วนที่สองคือ User Files ซึ่งเป็นส่วนที่อนุญาติให้ผู้ใช้แต่ละคนสามารถจัดการไฟล์ต่างๆได้ด้วยตัวเอง ระบบปฎิบัติการจะแยกไฟล์ของผู้ใช้แต่ละคนออกจากกัน ซึ่งผู้ใช้แต่ละคนจะมี Home Directory เป็นของตัวเอง

     

    Pathname
    คือชื่อที่ใช้ในการอ้างอิงที่อยู่ของไฟล์ แบ่งออกเป็น 2 แบบด้วยกัน แบบแรกคือ absolute path เป็นการบอกที่อยู่ของไฟล์หรือโฟลเดอร์โดยมีจุดเริ่มต้นที่ root ซึ่งแทนด้วยเครื่องหมาย / และอยู่ตำแหน่งหน้าสุดของ path เสมอ ส่วนเครื่องหมาย / ต่อมาจะหมายถึง sub folder ยกตัวอย่างเช่นไฟล์ chapter_1.pdf ในรูปมี path คือ /User/Ter/Download/chapter_1.pdf
    แบบที่สองคือ relative path จะเป็นการอ้างอิงกับตำแหน่งของโฟลเดอร์ที่กำลังทำงานในขณะนั้น เช่น สมมติว่ากำลังทำงานอยู่ที่ home directory เมื่อต้องการจะอ้างถึงไฟล์ chapter_1.pdf ก็จะได้ว่า Download/chapter_1.pdf
    นอกจากเครื่องหมาย / จะใช้แทน root แล้วยังมีสัญลักษณ์พิเศษอีก 3 อย่างด้วยกัน อย่างแรกคือ ~ ที่ใช้แทน home directory เช่น สมมติว่าตอนนี้ผู้ใช้คือ Ter เราสามารถเขียน path ของไฟล์ chapter_1.pdf โดยใช้ ~ ได้ดังนี้ ~/Download/chapter_1.pdf อย่างที่สองคือ . (จุด) หมายถึงโฟลเดอร์ที่ใช้งานขณะนั้น และสุดท้ายคือ .. ( จุด จุด ) หมายถึงโฟลเดอร์ชั้นหน้า (parent folder) ของโฟลเดอร์ที่ใช้งานปัจจุบัน

     

    NSFileManager

    คลาสเกี่ยวกับไฟล์คลาสแรกที่ Foundation Framework ได้เตรียมไว้ก็คือ NSFileManger คลาสนี้มีเมธอดพื้นฐานอยู่หลายเมธอดด้วยกัน อาทิเช่น การสร้างไฟล์ คัดลอกไฟล์ การย้ายไฟล์หรือไดเรกทอรี รวมไปถึงการขอข้อมูลเบี้องต้นของไฟล์และโฟลเดอร์เช่น ขนาดของไฟล์ วันที่เปลี่ยนแปลงล่าสุด คลาสนี้ยังมีเมธอดเกี่ยวกับการจัดการไฟล์ในระบบเคลือข่ายแบบกลุ่มเมฆ1 อีกด้วย แต่สามารถใช้ได้กับระบบปฎิบัติการ Mac OS X 10.7 และ iOS 5.0 ขึ้นไป การใช้งานโดยส่วนใหญ่สามารถทำผ่านออบเจ็กต์ที่เรียกว่า shared object ซึ่งเป็นออบเจ็กต์ที่มีคุณลักษณะพิเศษคือออบเจ็กต์นี้มีเพียงแค่ออบเจ็กต์ เดียวและใช้ร่วมกันทั้งโปรแกรม หรือเรียกว่า Singleton อีกทั้งยังรองรับการทำงานร่วมกันหลาย thread (thread safe) อย่างไรก็ตามเรายังสามารถที่จะสร้างออบเจ็กต์ของคลาสนี้ได้ตามปกติ

     

    Program 11.1
    Main.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    
    #import <Foundation/Foundation.h>
     
    int main(int argc, const char * argv[])
    {
     
        @autoreleasepool {
     
            // Create an instane of file manager.
            NSFileManager* fileMgr = nil;
            fileMgr = [NSFileManager defaultManager];
     
            // User desktop folder
            NSString* desktop = [NSString stringWithFormat:@"%@/Desktop",NSHomeDirectory()];
     
            NSString* filePath = [NSString stringWithFormat:@"%@/test.txt",desktop];
     
            if([fileMgr fileExistsAtPath:filePath])
            {
                NSError* error;
                BOOL copyResult;
                BOOL renameResult;
                BOOL compareResult;
     
                NSString* newPath = [NSString stringWithFormat:@"%@/copy.txt",desktop];
     
                // Content of file 
                NSLog(@"%@", [NSString stringWithContentsOfFile:
                              filePath encoding:NSUTF8StringEncoding error:NULL]);
     
                // Copy
                copyResult = [fileMgr copyItemAtPath:filePath toPath:newPath error: &error];            
                if (copyResult == NO)
                    NSLog(@"Copy failed :%ld" ,error.code );
     
                // Compare
                compareResult = [fileMgr contentsEqualAtPath:filePath andPath:newPath];
                if( compareResult == NO)
                    NSLog(@"Files are not equal");
     
                // Rename
                NSString* newFileName = [NSString stringWithFormat:@"%@/clone.txt",desktop];
     
                renameResult = [fileMgr moveItemAtPath:newPath toPath:newFileName error:&error];
     
                // Info
                NSDictionary* attDict = [fileMgr attributesOfItemAtPath:newFileName error:nil];
                NSLog(@"File type %@",[attDict objectForKey: NSFileType]);
                NSLog(@"File size %@",[attDict objectForKey: NSFileSize]);
     
                // Delete
                if ([fileMgr removeItemAtPath:newFileName error: &error] == NO)
                    NSLog(@"Delete failed :%ld",(long)error.code);
            }
            else
                NSLog(@"File doesn't exist");
     
        }
        return 0;
    }

     

    Program 11.1 Output

    Test Text 123
    File type NSFileTypeRegular
    File size 13

     

    โปรแกรมที่ 11.1 นี้เป็นโปรแกรมตัวอย่างสาธิตการใช้งานเมธอดต่างๆของคลาส NSFileManager โปรแกรมจะเริ่มด้วยการสร้าง shared object ของ NSFileManager ด้วยเมธอด defaultManager จากนั้นบรรทัดที่ 13 ใช้ฟังก์ชั่น NSHomeDirectory ขอที่อยู่ home directory ของผู้ใช้งานคนปัจจุบัน เพื่อจะนำมาใช้ในการสร้าง path ของไฟล์ test.txt ที่อยู่ในโฟลเดอร์ Desktop ต่ออีกทีหนึ่ง เพื่อให้แน่ใจว่ามีไฟล์นี้อยู่จริง เราเรียกเมธอด fileExistsAtPath: เพื่อทำการตรวจสอบ เมื่อตรวจสอบเรียบร้อยโปรแกรมก็จะแสดงข้อมูลในไฟล์ ต่อมาบรรทัดที่ 32 โปรแกรมจะคัดลอกไฟล์

     

     copyResult = [fileMgr copyItemAtPath:filePath toPath:newPath error: &error];

     

    สิ่งที่น่าสนใจของคำสั่งนี้คือพารามิเตอร์สุดท้ายนั้นรับ address of pointer ของ NSError ดังนั้นเราจึงต้องประกาศพอยน์เตอร์ และส่ง adress ของพอยน์เตอร์นั้น ด้วยการใส่เครื่องหมาย & นำหน้า เมื่อเกิดข้อผิดพลาดขึ้นมาเมธอดนี้จะส่งค่ากลับมายังพอยน์เตอร์ของเราพร้อม รายละเอียดต่างๆ เช่น error code เป็นต้น ในกรณีที่ไม่เกิดข้อผิดพลาด error ก็จะเป็น nil และค่า copyResult จะเป็น YES จากนั้นโปรแกรมจะทำการเปรียบเทียบไฟล์ที่คัดลอกกับไฟล์ต้นฉบับ จากนั้นบรรทัดที่ 42 ก็จะเปลี่ยนชื่อไฟล์ และเราเรียกเมธอด attributeOfItemAtPath เพื่อขอรายละเอียดของไฟล์ เมื่อเราเปิดดู API Document2 จะเห็นว่าเมธอดนี้จะให้ NSDirctionary กลับมา


    ch11_2

     

    ดิกชันนารีที่ได้กลับมานี้จะมี key ต่างๆซึ่งจะอธิบายในส่วนของ File Attribute Keys และเมื่อเราเปิดไปดูที่ File Attribute Keys ก็จะเห็นว่ามีคีย์หลายอย่างมาก เช่น NSFileSize เพื่อหาขนาดของไฟล์ เป็นต้น และสุดท้ายก็ลบไฟล์ที่ที่เราได้คัดลอกจากต้นฉบับ

     

    ch11_3

     

    โปรแกรมที่เราได้เขียนไปเป็นเพียงแค่การสาธิตการใช้งานในส่วนของเมธอดที่ เกี่ยวกับไฟล์เท่านั้น  คลาส NSFileManager ยังมีเมธอดที่เกี่ยวกับ Directory หรือ Folder

     

    Program 11.2
    Main.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    #import <Foundation/Foundation.h>
     
    int main(int argc, const char * argv[])
    {
     
        @autoreleasepool {
     
            NSFileManager* fileMgr = [NSFileManager defaultManager];
     
            NSLog(@"Current directory path is %@", [fileMgr currentDirectoryPath]);
     
            NSString* desktop = [NSString stringWithFormat:@"%@/Desktop",NSHomeDirectory()];
     
            // Change directory
            if( [fileMgr changeCurrentDirectoryPath:desktop] == NO)
                NSLog(@"Change failed");
     
            // Create a new directory
            NSError* error;
            if( [fileMgr createDirectoryAtPath:@"testDir" withIntermediateDirectories:YES
                                    attributes:nil error:&error] == NO)
            {
                NSLog(@"Create failed");
            }
     
            // Rename a directory
            if ([fileMgr moveItemAtPath:@"testDir" toPath: @"demoDir" error: NULL] == NO)
                NSLog(@"Rename failed");
     
        }
        return 0;
    }

     

    โปรแกรมที่ 11.2 เริ่มจากการแสดงโฟลเดอร์ที่กำลังทำงานอยู่ หลังจากนั้นก็เปลี่ยนมาที่ Desktop ของผู้ใช้ และบรรทัดที่ 20

     

            if( [fileMgr createDirectoryAtPath:@"testDir" withIntermediateDirectories:YES
                                    attributes:nil error:&error] == NO)
            {
                NSLog(@"Create failed");
            }

     

    เมธอดนี้รับพารามิเตอร์ถึง 4 ค่าด้วยกัน ค่าแรกคือชื่อของโฟลเดอร์ที่ต้องการ เมธอดนี้รองรับ path ทั้งแบบ absolute path และ relative path ในตัวอย่างเราใช้ relative path ดังนั้นแล้วโฟลเดอร์ก็จะถูกสร้างที่ Desktop ของผู้ใช้ ส่วนค่าที่สองหากระบุให้เป็น YES ในกรณีที่ไม่มี parent folder ที่กำหนด โปรแกรมจะสร้างโฟลเดอร์ให้ใหม่รวมถึง parent folder ด้วย เช่น สมมติว่าโปรแกรมทำงานที่ Desktop และถ้าเรากำหนด path เป็น Test/Demo แต่ยังไม่มีโฟลเดอร์ Test โปรแกรมก็จะสร้างทั้งสองโฟรเดอร์คือ Test และ Demo ต่อมาเป็นพารามิเตอร์ที่สามเป็นการกำหนดค่า attribute ให้กับโฟลเดอร์ แต่เราไม่ต้องการกำหนดอะไรเป็นพิเศษจึงใส่ค่า nil และพารามิเตอร์สุดท้ายคือค่า error (ใส่เป็น nil ก็ได้) เมื่อเราสร้างโฟลเดอร์เรียบร้อยแล้ว แต่ไปก็เปลี่ยนชื่อของโฟลเดอร์ เมื่อโปรแกรมทำงานจบลง ที่ Desktop ก็จะมีโฟลเดอร์ที่เราได้สร้างขึ้นนั่นเอง

     

    Program 11.2 Output

    Current directory path is /Users/Ter/Library/Developer/Xcode/DerivedData/Program_11.2-exeytenwzmypuzeedbcamrujncfg/Build/Products/Debug

     

    เราจะเขียนโปรแกรมเกี่ยวกับโฟลเดอร์อีกสักโปรแกรม โดยโปรแกรมนี้จะแสดงรายชื่อไฟล์ที่อยู่ในโฟลเดอร์ที่เรากำหนด และแสดงออกมาทาง console ซึ่งมีโค้ดดังต่อไปนี้

     

    Program 11.3
    Main.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    
    #import <Foundation/Foundation.h>
     
    int main(int argc, const char * argv[])
    {
     
        @autoreleasepool {
     
            NSFileManager* fileMgr = [NSFileManager defaultManager];
            NSDirectoryEnumerator* dirEnum;
     
            NSString* desktop = [NSString stringWithFormat:@"%@/Desktop",NSHomeDirectory()];
     
            // Change to home folder
            if( [fileMgr changeCurrentDirectoryPath:desktop] == NO)
                NSLog(@"Change failed");
     
            // First way
            NSString* currentPath = [fileMgr currentDirectoryPath];
            dirEnum = [fileMgr enumeratorAtPath: currentPath];
     
            for ( id item in dirEnum)
            {
                BOOL flag;
     
                if([fileMgr fileExistsAtPath:item isDirectory:&flag] == NO)
                    NSLog(@"Path does not exist");
     
                if( flag == YES)
                    [dirEnum skipDescendants];
     
                NSLog(@"%@",item);
     
            }
            NSLog(@"-------");
            // Another way
            NSArray* items = [fileMgr contentsOfDirectoryAtPath:currentPath error:nil];
            for ( id item in items)
                NSLog(@"%@",item);
     
        }
        return 0;
    }

     

    Program 11.3 Output

    Chapter_7.pdf
    Chapter_9.pdf
    untitled folder
    untitled folder/Chapter_10.pdf
    ——-
    Chapter_7.pdf
    Chapter_9.pdf
    untitled folder

     

    โปรแกรมที่ 11.3 จะแสดงไฟล์และโฟลเดอร์ตาม path ที่เราได้กำหนดไว้ ซึ่งมีด้วยกันสองวิธีคือ แบบแรกใช้เมธอด enumeratorAtPaht: ส่วนวิธีที่สองใช้เมธอด contentsOfDirectoryAtPath: เมธอดทั้งสองนี้สามารถแสดงไฟล์และโฟลเดอร์ได้เหมือนกัน แต่ผลลัพธ์แตกต่างกัน โดยแบบแรกนั้นจะแสดงโฟรเดอร์ย่อยด้านใน รวมถึงไฟล์ที่อยู่ในโฟลเดอร์ย่อยอีกด้วย เช่นตัวอย่าง output จะเห็นว่าแบบแรกได้แสดงโฟลเดอร์ untitled folder และไฟล์ Chapter_10.pdf ด้วย ส่วนเมธอดที่สองนั้นจะแสดงแค่ชื่อของโฟลเดอร์ untitled folder เท่านั้น ไม่ได้แสดงรายการภายใน
    อย่างไรก็ตาม เราสามารถที่จะทำให้เมธอดแรกนั้นแสดงผลลัพธ์เหมือนอย่างวิธีที่สองได้เช่น กัน โดยการเพิ่มเติมโค้ดในการตรวจสอบว่าถ้าหาก path นั้นเป็นโฟลเดอร์ก็เรียกเมธอด skipDescendants เพื่อให้ข้ามการทำงาน ดังเช่นตัวอย่าง

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
            for ( id item in dirEnum)
            {
                BOOL flag;
     
                if([fileMgr fileExistsAtPath:item isDirectory:&flag] == NO)
                    NSLog(@"Path does not exist");
     
                if( flag == YES)
                    [dirEnum skipDescendants];
     
                NSLog(@"%@",item);
     
            }

     

    เมธอด fileExistsAtPath:isDirectory นั้นจะส่งค่ากลับมาเป็น YES ในกรณีที่ path นั้นมีอยู่จริง ส่วนค่า flag จะได้กลับมาเป็น YES ในกรณี path นั้นเป็นโฟลเดอร์

บทความที่น่าสนใจ

บทความ ล่าสุด

บทความ ความรู้ด้านไอที, คอมพิวเตอร์ Techonlogy, Gadget, ความรู้เกี่ยวกับคอมพิวเตอร์ กับทาง SoftMelt.com