• OC基础14:使用文件


      "OC基础"这个分类的文章是我在自学Stephen G.Kochan的《Objective-C程序设计第6版》过程中的笔记。

    1、对于NSFileManager类,文件的路径名的标识只能是文件名或目录。每个路径名都是一个NSString对象。这个路径可以是相对路径,也可以是绝对路径。

    2、绝对路径以斜线/开始,斜线即是根目录。特殊的代字符~标识用户的主目录。但是在程序中应尽量避免使用硬编码的路径名,应使用方法和函数来处理路径或文件。

    3、所有对文件的操作都要通过对NSFileManager类的操作,NSFileManager类的对象可以理解为是一个文件处理的代理,所有的操作都要通过这个代理来完成。

    4、NSFileManager类的创建方法如下:

        NSFileManager fm;

        fm = [NSFileManager defaultManager];

    然后就可以通过对fm对象的操作来操作文件,比如要在当前目录删除名为“todolist”的文件,可以使用以下代码:

        if([fm removeItemAtPath: @”todolist” error:NULL] == NO) {

          NSLog(@”couldn’t remove”);

          return 1;

        }

    可以注意到,方法是有返回值的,是一个BOOL值。

      

    5、以下代码展示了NSFileManager类主要的文件操作方法:

       (1)、...

       NSString *fName = @”testfile”;

       NSFileManager *fm;

       fm = [NSFileManager defaultManager];

      

       if([fm fileExistsAtPath: fName] == NO) {

         NSLog(@”not exsit”);

         [fm creatFileAtPath:fName contents:nil attributes:nil];

         return 1;  

       }

       ...

       注意fileExistsAtPath:方法也是有返回值的,是一个bool类型的值;

       (2)、...

       if([fm copyItemAtPath:fName toPath:@”newfile” error:NULL] == NO) {

         NSLog(@”copy file failed”);

         return 2;

       }

       ...

       复制文件;

      (3)、...

      if([fm contentsEqualAtPath:fName andPath:@”newfile”] == NO) {

        NSLog(@”files are not equal”);

        return 3;  

       } 

       ...

       比较两个文件是否相同;

       (4)、...

       if([fm moveItemAtPath:@”newfile” toPath:@”newfile2” error:NULL] == NO){

         NSLog(@”file rename failed”);

         return 4;

       }

       ...

       重命名文件;

       (5)、...

       NSDictionary *attr;

       if((attr = [fm attributesOfItemAtPath:@”newfile2” error:NULL]) == nil){

         NSLog(@”couldn’t get file attributes”);

         return 5;

       }

       NSLog(@”file size is %llu”, [[attr objectForKey: NSFileSize] unsignedLongLongValue]);

       ...

       获取文件的大小,attributesOfItemAtPath:的返回值是一个NSDictionary类对象,最后要使用键“NSFileSize”读取出文件的大小;

       (6)、...

       if([fm removeItemAtPath:fName error:NULL] == NO){

         NSLog(@”file removal failed”);

         return 6;

       }

       ...

       删除文件,同样要注意removeItemAtPath:函数的返回值是BOOL类型;

       (7)、...

       NSLog(@”%@”, [NSString stringWithContentsOfFile:@”newfile2” encoding: NSUTF8StringEncoding error:NULL]);

       ...

       显示newfile2文件的内容;

       (8)、使用方法copyItemAtPath:toPath: error:复制文件或方法moveItemAtPath:toPath:error:移动文件的时候,如果只指定目标目录,是无法将文件复制或移动到这个目录中的,需要明确地指定目标目录中的文件名;

       (9)、方法moveItemAtPath:toPath:error:不只是用来移动文件,也可以移动目录。如果两个路径引用的是同一个目录中的文件,则效果仅仅是重命名这个文件;

       (10)、stringWithContentsOfFile:encoding:error:方法中,encoding参数是用来指定文件中的字符要如何显示,使用NSUTF8StringEncoding表示文件包含常规的UTF8 ASCII字符;

       (11)、这个测试程序中,在每个可能发生错误的地方return了不同的数字,这样在调试的时候就可以通过返回值判断错误发生的地方。

    6、关于NSData类:

       (1)、NSData类对象是一个文件内容的缓存区,将文件内容读入缓存区,或是将缓存区的内容写入文件。理论上NSData对象可以存储2GB到8EB的数据;

       (2)、理解以下代码:

       ...

       NSData *fileData;

       fileData = [fm contentsAtPath:@”newfile2”];   //从newfile2中读取内容

       if([fm createFileAtPath:@”newfile3” contents:fileData attributes:NULL] == NO) {

         NSLog(“couldn’t create file”);       //把内容写入到newfile3中去

         return 1;

       } //在if语句里向新文件写入了内容,其实用的还是createFileAtPath:方法

    7、以下代码展示了NSFileManager类主要的目录操作方法:

       (1)、...

       path = [fm currentDirectoryPath];

       NSLog(@”the current path is %@”, path);

       ...

       获取当前的目录;

       (2)、...

       NSString *dirName = @”testdir”;

       if([fm createDirectoryAtPath:dirName withIntermediaDirectories:YES attributes:nil error:NULL] == NO) {

         NSLog(@”couldn’t create directory”);

         return 1;

       }

       ...

       在当前目录下创建新目录;

       (3)、...

       if([fm moveItemToPath:dirName toPath:@”newdir” error:NULL] == NO) {

         NSLog(@”directory rename failed”);

         return 2;

       }

       ...

       重命名文件夹,这个方法其实也是重命名文件的方法;

       (4)、...

       if([fm changeCurrentDirectoryPath:@”newdir”] == NO) {

         NSLog(@”change directory failed”);

         return 3;

       }

       ...

       更改当前目录为新的目录;

      

    8、关于枚举目录的内容,有两种方式,看以下代码:

       ...

       NSString *path;  //当前路径,定义过程忽略

       NSFileManager *fm;  //定义过程忽略

       NSDirectoryEnumerator *dirEnum;

       NSArray *dirArray;

       ...

       //第一种枚举方法,使用NSEnumerator类

       dirEnum = [fm enumeratorAtPath: path];

       NSLog(@”contents of %@”, path);

       while((path = [dirEnum nextObject]) != nil) { //nextObject是NSEnumerator才有的方法

         NSLog(@”%@”, path);

       }

       ...

       //第二种枚举方法

       dirArray = [fm contentsOfDirectoryAtPath: [fm currentDirectoryPath] error:NULL];

       for(path in dirArray) {

         NSLog(@”%@”, path);

       }

       ...

       关于这两个方法:

       (1)、使用enumeratorAtPath:方法不仅可以枚举目录中的文件,甚至目录中包含目录的话,还会递归枚举子目录的内容,甚至子目录的子目录的内容,它会穷尽枚举出这个文件夹下所有的文件。而使用contentsOfDirectoryAtPath:方法则仅仅只是枚举出目录下一级的内容;

       (2)、两个方法都会枚举出所有类型的文件,甚至包括文件夹;

       (3)、使用以下方法可以阻止enumeratorAtPath:方法递归枚举子文件夹的内容:

           ...

           while((path = [dirEnum nextObject]) != nil) {

             NSLog(@”%@”, path);

             [fm fileExsitsAtPath: path isDirectory:&flag]

             //使用这个方法可以判断在dirEnum中读取到的内容是不是文件夹,

             //如果是文件夹则flag会被置为YES;

             if(flag == YES) {

               [dirEnum skipDescendents]; //这个方法可以阻止dirEnum枚举子文件夹

             }

           }

           ...

    9、关于使用路径的一些方法:

       (1)、路径名的操作主要是使用NSPathUtilities.h提供的方法,NSPathUtilities.h包含在Foundation.h中。如下代码演示:

       (2)、...

           NSString *tempdir;

           tempdir = NSTemporaryDirectory();

           NSLog(@”temporary directory is %@”, tempdir);

           ...

           获取当前临时目录;

       (3)、...

           NSString *path;

           NSFileManager *fm;

           fm = [NSFileManager defaultManager];

           path = [fm currentDirectoryPath];

           NSLog(@”base dir is %@”, [path lastPathComponent]);

           ...

           获取基本文件名或文件夹名,即是路径的最后一个组成部分的名字;

       (4)、...

           NSString *fName = @”path.m”;

           NSString *fullpath;

           fullpath = [path stringByAppendingPathComponent: fName];

           NSLog(@”fullname to %@ is %@”, fName, fullpath);

           ...

           获取完整路径,包括文件名;
       (5)、...

           NSString *extension;

           extension = [fullpath pathExtension];

           NSLog(@”extension for %@ is %@”, fullpath, extension);

           ...

           获取文件的扩展名,如果没有扩展名则返回一个空字符串;

       (6)、...

           NSString *homedir;

           homedir = NSHomeDirectory();

           NSLog(@”your home directory is %@”, homedir);

           ...

           获取用户的主目录,如果使用NSHomeDirectoryForUser()还可以获取其他用户的主目录;

       (7)、...

           NSArray *component;

           component = [homedir pathComponent];

           for(path in component) {

             NSLog(@”%@”, path);

           }

           ...

           将主目录的每一个组成部分拆开存放在数组中;

    10、关于使用NSFileHandle类对文件的操作:

    (1)、...

        NSFileHandle *inFile;

        inFile = [NSFileHandle fileHandleForReadingAtPath:@”testfile”];

        ...

        设置testfile文件为读取对象;

    (2)、...

        NSFileHandle *outFile;

        outFile = [NSFileHandle fileHandleForWritingAtPath:@”testout”];

        ...

        设置testout文件为写入对象;

    (3)、...

        [outFile truncateFileAtOffset:0];

        ...

        把文件截取到只剩几个字节;

    (4)、...

        NSData *buffer;

        buffer = [inFile readDataToEndOfFile];

        [outFile writeData: buffer];

        ...

        把inFile的内容写入到outFile;

    (5)、...

        [inFile closeFile];

        [outFile closeFile];

        ...

        要记得关闭文件;

    (6)、...

        NSLog(@”%@”, [NSString stringWithContentsOfFile:@”testout” encoding: NSUTF8StringEncoding error:NULL]);

        ...

        读取testout文件内的内容;

    11、文件中锚点位置的偏移:

    假设已定义好文件fileA和文件fileB,定义好读取文件的操作fileHandleA和写入文件的操作fileHandleB,如果要将fileA的内容附加到fileB的后面,则要把fileB的锚点设置到文件的最后,使用以下方法:

    [fileHandleA seekToEndOfFile];

    则此时使用以下语句往fileB写入内容的话:

    buffer = [fileHandleA readDataToEndOfFile];

    [fileHandleB writeData: buffer];

    则fileHandleB对应的文件的内容就是fileB加上fileA;

    12、另外,关于锚点位置的偏移:

    (1)、想要定位到文件的第10字节,可以使用以下方法(假设文件的句柄为xxxHandle):

            [xxxHandle seekToFileOffset: 10];

    (2)、如果想要跳过文件中当前位置之后的128字节,可以使用以下方法:

            [xxxHandle seekToFileOffset: [xxxHandle offsetInFile] + 128 ];  

    (3)、要在文件中回移5个整数所占的字节数,可以使用以下方法:

            [xxxHandle seekToFileOffset: [xxxHandle offsetInFile] – 5 * sizeof(int)];

      

    13、NSURL类是通过文件的http地址读取内容,以下是一个NSURL类的例子:

    ...

    NSURL *myURL = [NSURL URLWithString: @”http://xxx.com”];

    NSString *myHomePage = [NSString stringWithContentsOfURL:myURL

    encoding:NSASCIIStringEncoding error:NULL];

    ...

  • 相关阅读:
    [译]ASP.NET 5 Configuration
    loopback文档翻译
    [译]Testing Node.js With Mocha and Chai
    [译]在Node中使用indicative来验证model
    机器学习:计算机学习西洋跳棋
    OpenCV成长之路(10):视频的处理
    OpenCV成长之路(9):特征点检测与图像匹配
    OpenCV成长之路(8):直线、轮廓的提取与描述
    OpenCV成长之路(7):图像滤波
    OpenCV成长之路(6):数学形态学基本操作及其应用
  • 原文地址:https://www.cnblogs.com/shayneyeorg/p/4861129.html
Copyright © 2020-2023  润新知