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

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

Objective-C : Foundation Framework (ตอนที่3)

    Read string from & Write String to file

    คลาส NSString มีเมธอดที่ใช้ในการอ่านและเขียนไฟล์ อย่างง่ายอยู่แล้ว (คลาสที่เกี่ยวข้องกับการใช้ไฟล์โดยตรงจะอธิบายในบทหลังๆ) เช่น

     

    +(id)stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error;
    - (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)
    enc error:(NSError **)error;

     

    เราสามารถใช้เมธอดเหล่านี้เพื่ออ่านและเขียนไฟล์ได้ ดังโปรแกรมตัวอย่างต่อไปนี้

     

    Program 8.9

    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
    
    #import <Foundation/Foundation.h>
     
    int main(int argc, const char * argv[])
    {
     
        @autoreleasepool {
     
            NSString* text = @"String objects represent character strings in Cocoa frameworks.\n"
            "Representing strings as objects allows you to use strings\n"
            "wherever you use other objects\n";
     
            NSError *error;
            NSMutableString* path = [NSMutableString string];
            [path setString:[NSHomeDirectory() stringByAppendingPathComponent:@"Desktop"]];
            [path appendString:@"/program_data.txt"];
     
            [text writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error ];
            if( error == nil)
            {
                NSString* strFromFile = [NSString stringWithContentsOfFile:path
                                                                  encoding:NSUTF8StringEncoding
                                                                     error:&error];
                NSLog(@"%@",strFromFile);
            }
     
        }
        return 0;
    }

    Program 8.9 Output

    String objects represent character strings in Cocoa frameworks.
    Representing strings as objects allows you to use strings
    wherever you use other objects

     

    การทำงานของโปรแกรม 8.9 โดยคร่าวๆ คือเราได้ประกาศสตริง และโปรแกรมเรียกใช้ฟังชั่น NSHomeDirectory() โดยจะได้ค่าที่เป็น Path ของ Home User เมื่อได้ Home User path แล้วต่อไปก็เพื่อกำหนดที่อยู่ของไฟล์ที่ต้องจะเขียนไปยัง Desktop และให้ไฟล์มีชื่อว่า program_data.txt หลังจากำหนด path เรียบร้อยก็เขียนไฟล์ด้วยคำสั่ง

     

    17
    
            [text writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&amp;error ];</td>

    ไฟล์ที่เขียนไปเราได้กำหนดให้ encode ด้วย UTF8 และการกำหนดให้เป็น atomically หมายถึงว่าโปรแกรมจะเขียนไฟล์ไปยังตำแหน่งไฟล์ชั่วคราวที่ระบบได้สร้างขึ้น (auxiliary file) เมื่อเขียนเสร็จเรียบร้อยถ้าไม่มีข้อผิดพลาดใดๆ โปรแกรมจะคัดลอกไปยังตำแหน่งที่เราได้ระบุไว้ แต่ในกรณีที่เกิดข้อผิดพลาดเป็นต้นว่าฮาร์ดดิสเต็มก่อนที่จะเขียนเสร็จ ไฟล์จะไม่ได้ถูกคัดลอกไปยังตำแหน่งที่กำหนด (ถ้าไฟล์อยู่แล้วจะถูกเขียนทับ) หลังจากที่โปรแกรมได้เขียนไฟล์เสร็จเรียบร้อยแล้ว โปรแกรมก็จะอ่านไฟล์ที่เพิ่ง

     

    เขียนไปและแสดงข้อมูล

     

    NSScaner

    โปรแกรมที่ผ่านๆมาเราได้ใช้เมธอดของคลาส NSString เพื่อใช้ค้นหาตำแหน่งของข้อความที่ต้องการ แต่ก็เป็นเพียงแค่การหาตำแหน่งแบบง่ายๆ ในการหาตำแหน่งของข้อมูลแบบละเอียด Foundation Framework ได้มีคลาสที่ช่วยค้นหาข้อมูลที่ต้องการไว้ให้อยู่แล้วนั่นก็คือ NSScaner

     

    โปรแกรมที่จะได้เขียนต่อไปคือ XML Parser อย่างง่าย เพื่อทดลองการใช้ NSScaner แต่ก่อนจะลงมือเขียนโค้ดให้สร้างโปรเจคขึ้นมาใหม่ และเมื่อสร้างโปรเจคเสร็จแล้วให้ เพิ่มไฟล์ data.txt เข้าไปยังโปรเจคของเราจากเมนู New File แล้วเลือก Empty File ดังรูป

     

    Objective-C : Foundation Framework (ตอนที่3)

     

    เมื่อสร้างไฟล์ใหม่เรียบร้อย แล้วให้ไปที่ Build Phases ดังรูป

     

    Objective-C : Foundation Framework (ตอนที่3)

     

    และกดที่ปุ่มด้านขวามือสุด Add Build Phase แล้วเลือก Add copy file เมื่อเสร็จแล้ว จะเห็นแถบบาร์สีเทาเพิ่มขึ้นมาว่า CopyFiles ( 0 item) ให้กดที่รูปสามเหลี่ยมด้านซ้าย และเลือก + จะเจอหน้าต่างให้เลือกไฟล์ ให้เลือก data.txt แล้วตั้ง Destination ให้เป็น Resources เสร็จแล้วจะได้ดังรูป

     

    Objective-C : Foundation Framework (ตอนที่3)

     

     

    ที่เราได้ทำไปทั้งหมดคือ เราได้สร้างไฟล์ขึ้นมาใหม่เพื่อเป็นข้อมูลของโปรแกรม แล้วหลังจากนั้นเราก็เพิ่มขั้นตอนในการ Build ไปอีก 1 ขั้นตอน นั่นก็คือการคัดลอกไฟล์ data.txt ไปไว้ยังที่เดียวกับโปรแกรม ( excuteable file ) เพื่อความสะดวกในการเรียกใช้งานเมื่อทำขึ้นตอนเหล่านี้เสร็จเรียบร้อยต่อไปเราจะลงมือเขียนข้อมูลในไฟล์ data.txt ดังนี้

     

    <?xml version="1.0">
    <product>
    <name>Red Furby</name>
    <price>3400</price>
    </product>
     
    <product>
    <name>Blue Furby</name>
    <price>2700</price>
    </product>
     
    <product>
    <name>Green Furby</name>
    <price>4200</price>
    </product>

     

    เมื่อเขียนข้อมูลในไฟล์ data.txt เรียบร้อยแล้วต่อไปเราจะสร้างคลาสชื่อว่า Parser

     

    1
    2
    3
    4
    5
    6
    7
    8
    
    //Parser.h
     
    #import <Foundation/Foundation.h>
     
    @interface Parser : NSObject
    +(NSString *)getString:(NSString *)string tag:(NSString *)tag location:(int)location;
     
    @end

     

    คลาส Parser มีเพียงคลาสเมธอดที่รับสตริง และ XML Tag ที่ต้องการ พร้อมกับตำแหน่งที่จะเริ่มค้นหา

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    //Parser .m
     
    #import "Parser.h"
     
    @implementation Parser
     
    +(NSString *)getString:(NSString *)string tag:(NSString *)tag location:(int)location
    {
        NSString *ret = nil;
        if( string != nil)
        {
            NSScanner *scanner = [[NSScanner alloc] initWithString:string];
            [scanner setScanLocation:location];
            [scanner scanUpToString:[NSString stringWithFormat:@"<%@>",tag] intoString:nil];
            [scanner scanString:[NSString stringWithFormat:@"<%@>",tag] intoString:nil];
            [scanner scanUpToString:[NSString stringWithFormat:@"</%@>",tag] intoString:&ret];
            [scanner release];
        }
        return ret;
    }
     
    @end

     

    ในส่วนของ implementation ได้ประกาศ scaner และกำหนดตำแหน่งเริ่มต้นของการค้นหา ( ในกรณีที่ไม่ได้ตั้งค่าจะเริ่มที่ 0 )สมมติว่ามีข้อมูลคือ <?XML> <Name> Furby </name> เมื่อเริ่มทำงานสแกนเนอร์จะเริ่มต้นที่ตำแหน่งที่กำหนด

    image_1-1

    จากนั้นเราก็จะสแกนสตริงที่ต้องการด้วย scanUpToString

     

    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
            [scanner scanUpToString:[NSString stringWithFormat:@"<%@>",tag] intoString:nil];
    <pre>
    เมื่อสแกนเนอร์เจอสตริงที่ต้องการ สแกนเนอร์แยกเอาข้อมูลในตำแหน่งก่อนหน้า (intoString) 
    มาให้เราด้วย (ส่วนที่ตัวหนังสือเป็นสีเทา ) แต่ในส่วนโค้ดบรรทัดที่ 14 นี้เราไม่ต้องการ intoString จึงกำหนดค่าเป็น nil 
    เมื่อจบการทำงานบรรทัด 14 สแกนเนอร์จะมีตำแหน่งดังนี้
     
    <a href="http://macfeteria.com/wp-content/uploads/2013/02/image_1-2.png">
    <img class="alignnone size-medium wp-image-2104" alt="image_1-2" 
    src="http://macfeteria.com/wp-content/uploads/2013/02/image_1-2-300x45.png" width="300" 
    height="45" /></a>
     
    หลังจากนั้นเราจะให้สแกนเนอร์หาข้อมูลส่วนที่เป็น XML Tag ด้วยคำสั่ง scanString
     
    &nbsp;
    <pre lang="objc" line="15">
            [scanner scanString:[NSString stringWithFormat:@"<%@>",tag] intoString:nil];

     

    เมื่อค้นหาข้อมูลเจอสแกนเนอร์ก็จะขยับไปยังตำแหน่งท้ายของสตริงที่ค้นหา และเราก็ไม่ต้องการ intoString เช่นกัน

     

    image_1-3

     

    และสุดท้ายให้สแกนเนอร์หาส่วนปิดของ tag แต่คราวนี้เราต้องเก็บเอาค่า intoString เพราะเป็นค่าที่เราต้องการไว้ยัง ret

     

    16
    
            [scanner scanUpToString:[NSString stringWithFormat:@"</%@>",tag] intoString:&ret];

    image_1-4

    เมื่อเขียนส่วนเมธอดของคลาสเสร็จ เราก็จะเขียนส่วนของโปรแกรมเพื่อทดสอบการใช้งาน

     

    Program 8.10

    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
    
    #import <Foundation/Foundation.h>
    #import "Parser.h"
     
    int main(int argc, const char * argv[])
    {
     
        @autoreleasepool {
     
            NSError *error;
            NSMutableString* path = [NSMutableString string];
            [path setString:[[NSBundle mainBundle] bundlePath] ];
            [path appendString:@"/data.txt"];
     
     
            NSString* stringFromFile = [NSString stringWithContentsOfFile:path
                                                                 encoding:NSUTF8StringEncoding
                                                                    error:&error];
            int loc = 0;
            while (loc < stringFromFile.length)
            {
                NSString* item = [Parser getString:stringFromFile tag:@"product" location:loc];
                if( item != nil)
                {
                    NSString* name = [Parser getString:item tag:@"name" location:0];
                    NSString* price = [Parser getString:item tag:@"price" location:0];
                    NSLog(@"%@ %@",name , price);
                }
                else
                    break;
     
                loc += item.length + 10 ;
            }
     
            NSLog(@"%@",stringFromFile);
     
        }
        return 0;
    }

     

    เริ่มแรกกำหนด file path เป็น [[NSBundle mainBundle] bundlePath] ซึ่งเป็นตำแหน่งที่โปรแกรมทำงาน (เนื่องจากเราได้ให้XCode คัดลอกไฟล์ data.txt ไปยังตำแหน่งเดียวกับ execute file ใน Build Phase) และให้โปรแกรมได้เริ่มอ่านไฟล์

     

    หลังจากนั้น โปรแกรมจะเริ่มเข้าสู่ while loop โดยการทำงานภายในลูปคือเรากำหนดให้เริ่มสแกนหา tag ชื่อ product ถ้าหากไม่เจอก็ให้หยุดการทำงานของ loop

     

    19
    20
    21
    22
    23
    
            while (loc < stringFromFile.length)
            {
                NSString* item = [Parser getString:stringFromFile tag:@"product" location:loc];
                if( item != nil)
                {

     

    เมื่อเราได้ข้อมูลภายใน tag product มาแล้ว ลำดับต่อไปคือ ทำการแยกข้อมูลย่อยภาย โดยค้นหา name และ price

     

    24
    25
    26
    
                    NSString* name = [Parser getString:item tag:@"name" location:0];
                    NSString* price = [Parser getString:item tag:@"price" location:0];
                    NSLog(@"%@ %@",name , price);

     

    เมื่อเสร็จการแยกย่อยข้อมูล เราจะเลื่อนตำแหน่งของสแกนเนอร์ไปยังจุดท้ายสุดของ tag product ที่เราได้เจอในตอนแรก ( เลข10 คือค่าความยาวของสตริง </product> )

     

    31
    
                loc += item.length + 10 ;

     

    จากนั้นโปรแกรมก็จะวน loop เพื่อหา product ใหม่โดยเริ่มจากตำแหน่งล่าสุดที่ได้ค้นหาไป ผลลัพธ์ของโปรแกรมจึงเป็นดังนี้

     

     

    Program 8.10 Output

    Red Furby 3400
    Blue Furby 2700
    Green Furby 4200

     

     

    บทนี้เราก็ได้เรียนรู้เกี่ยวกับหัวใจหลักของ Objective-C นั่นก็คือ Foudation Framework และการประยุกต์นำไปใช้ จะเห็นว่า คลาสต่างๆภายใน Foundation นั้นมีประสิทธิภาพสูงและมีเมธอดต่างอำนวยความสะดวกมากมาย ความสนุกของการเขียนโปรแกรมด้วย Objective-C เพิ่งจะเริ่มต้นเท่านั้นครับ ในบทหน้าเราจะยังลุยกันต่อกับ Container Class ต่างๆเช่น NSArray

     

     

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

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

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