writeToFile не выполняет запись в файл

#objective-c #ios

#objective-c #iOS

Вопрос:

Ну, у меня возникла проблема, и я боролся с ней в течение нескольких дней. Вот оно: при попытке записи в XML-файл (размещенный в проекте xcode, который я разрабатываю) с использованием writeToFile запись не работает, и я ничего не вижу в XML-файле, хотя значение bool, возвращаемое из writeToFile, оценивается как true !! Кроме того, байты файла равны нулю. Итак, я был бы очень признателен, если кто-нибудь сможет мне в этом помочь. Ниже приведена часть кода, который я написал:

 //writing to a file
 NSString *pathOfFile = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"xml"];
 NSString *dummyString = @"Hello World!!n"; 
 NSFileManager *filemanager;

 filemanager = [NSFileManager defaultManager];

  //entering the first condition so I assured that the file do exists
  if ([filemanager fileExistsAtPath:pathOfFile] == YES)
     NSLog (@"File do exist !!!");
   else
     NSLog (@"File not found !!!");


BOOL writingStatus = [dummyString writeToFile:path atomically:YES encoding:NSUnicodeStringEncoding error:nil];

    //Not entering this condition so I am assuming that writing process is successful but when I open the file I can't find the string hello world and file size shows 0 bytes
    if(!writingStatus)
    {
        NSLog(@"Error: Could not write to the file");
    }
  

Я также пробовал эту альтернативу, но, к сожалению, она тоже не сработала.

 NSString *hello_world = @"Hello World!!n";
NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *directory = [paths objectAtIndex:0];
NSString *fileName = @"sample.xml";
NSString *filePath = [directory stringByAppendingPathComponent:fileName];
NSLog(@"%@",filePath);
BOOL sucess = [hello_world writeToFile:filePath atomically:YES encoding:NSASCIIStringEncoding error:nil];  
if(!sucess)
{
    NSLog(@"Could not to write to the file");
}
  

Комментарии:

1. Мы говорим здесь об iOS или macOS X? Пожалуйста, отметьте свой вопрос, чтобы указать это.

Ответ №1:

В первом фрагменте кода мы не видим определения path . Если это опечатка, и вы имели в виду file_path , проблема в том, что file_path указывает на путь внутри пакета приложений. Вы не можете записывать внутри своего пакета приложений. (Не должно быть никаких опечаток, потому что вы должны вставлять код напрямую.)

Во втором случае сложнее определить, в чем проблема. filePath должен находиться в каталоге documents, который доступен для записи. Однако было бы намного проще диагностировать проблему, если бы вы получали фактическую ошибку. Вместо того, чтобы передавать nil параметр ошибки в -writeToFile:atomically:encoding:error: , создайте NSError* переменную и передайте ее адрес. Если есть проблема, то ваш указатель будет установлен так, чтобы указывать на объект NSError, который описывает проблему.

Комментарии:

1. Да, я имел в виду file_path вместо path в первом разделе кода. Это опечатка, потому что я пытался определить другой путь, а потом забыл его изменить. Что касается второго фрагмента кода, я добавлю переменную ошибки для дальнейшей диагностики проблемы. Спасибо за вашу ценную информацию, это действительно помогло. Итак, нет никакого способа, которым мы могли бы записать в файл внутри пакета приложения?

2. @User897, нет, вы не должны записывать в свой пакет приложений . Даже если бы вы могли найти способ сделать это, ваши данные не были бы скопированы при синхронизации пользователя, и вы бы аннулировали подпись, позволяющую запускать приложение.

Ответ №2:

Тот факт, что writeToFile: возвращается логическое значение YES, просто означает, что вызов завершен.

Вы должны передавать NSError** в writeToFile: и проверять это, например:

  NSError *error = nil;
 BOOL ok = [hello_world writeToFile:filePath atomically:YES 
                        encoding:NSASCIIStringEncoding error:amp;error];
 if (error) {
      NSLog(@"Fail: %@", [error localizedDescription]);
 }
  

Это должно дать вам хорошее представление о том, что происходит не так (при условии, что ошибка не равна нулю после вызова).

Ответ №3:

 -(void)test{
//writing to a file
    NSError *error;
    NSString *pathOfFile = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@".xml"];//was missing '.'
NSString *dummyString = @"Hello World!!n";
NSFileManager *filemanager;

filemanager = [NSFileManager defaultManager];

//entering the first condition so I assured that the file do exists
   //the file exists in the bundle where you cannot edit it

    if ([filemanager fileExistsAtPath:pathOfFile]){
        NSLog (@"File do exist IN Bundle MUST be copied to editable location!!!");
        NSArray *locs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *docsDir = [[locs objectAtIndex:0]stringByAppendingString:@"dummyFile"];
        NSString *file = [docsDir stringByAppendingPathComponent:@".xml"];

        [filemanager copyItemAtPath:pathOfFile toPath:file error:amp;error];
    }
    else{
NSLog (@"File not found in bundle!!!");

    }

    if (error) {
        NSLog(@"error somewhere");
    }


//if youre only messing with strings you might be better off using .plist file idk
BOOL success = [dummyString writeToFile:file atomically:YES encoding:NSUnicodeStringEncoding error:nil];

//Not entering this condition so I am assuming that writing process is successful but when I open the file I can't find the string hello world and file size shows 0 bytes
if(!success)
{
    NSLog(@"Error: Could not write to the file");
}


}
  

Ответ №4:

 //I typically do something like this

//lazy instantiate a property I want such as array.
-(NSMutableArray*)array{
    if (!_array) {
        _array = [[NSMutableArray alloc]initWithContentsOfFile:self.savePath];
    }
    return _array;
}

//I'm using a class to access anything in the array from as a property from any other class
//without using NSUserDefaults.

//initializing the class
-(instancetype)init{

    self = [super init];
    if (self) {
    //creating an instance of NSError for error handling if need be.
        NSError *error;
    //build an array of locations using the NSSearchPath...  
        NSArray *locs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,     NSUserDomainMask, YES);
        //location 0 of array is Documents Directory which is where I want to create    the file
        NSString *docsDir = [locs objectAtIndex:0];
//my path is now just a matter of adding the file name to the docsDir
        NSString *path = [docsDir stringByAppendingPathComponent:@"fileName.plist"];
//if the file is a plist I have in my bundle I need to copy it to the docsDir to edit it

//I'll do that by getting it from the bundle that xCode made for me
        NSString *bunPath = [[NSBundle mainBundle]pathForResource:@"fileName"     ofType:@".plist"];


//now I need a NSFileManager to handle the dirty work
        NSFileManager *filemngr = [NSFileManager defaultManager];


//if the file isn't in my docsDir I can't edit so I check and if need be copy it.        
        if (![filemngr fileExistsAtPath:path]) {
            [filemngr copyItemAtPath:bunPath toPath:path error:amp;error];

//if an error occurs I might want to do something about it or just log it as in below.
//I believe you can set error to nil above also if you have no intentions of dealing with it.
            if (error) {
                NSLog(@"%@",[error description]);
                error = nil;

            }
//here I'm logging the paths just so you can see in the console what's going on while     building or debugging.
            NSLog(@"copied file from %@ to %@",bunPath,path);
        }

//in this case I'm assigning the array at the root of my plist for easy access
        _array = [[NSMutableArray alloc]initWithContentsOfFile:path];
        _savePath = path;//this is in my public api as well for easy access.

    }

    return self;
}