0

I had a look around, trying to find a straightforward method for first saving a MutableArray (which will contain different text arrays from UITextViews with returns etc.) into a txt-file and then loading the txt-file back into my MutableArray.

I didn't manage to come up with the reverse method (loading the text-file) and was wondering how I should go about this. I'm sure txt files and mutable arrays are not really compatible, especially if I want the MutableArray to hold various text strings from UITextViews.

Is there a way to mark the beginning of one section in a mutable array and the beginning of the next in a txt file? The aim would be to be able to edit the txt file both in the program and in a simple text editor without messing up the structure of the mutable array.

Can I use a certain special character (not \n obviously) in my text file so as to separate different objects?

Here is what I've come up with so far. Sorry, I'm a beginner and it's very basic. The first problem is that I get the error message 'NSMutableArray' may not respond to '-writeToFile:atomically:encoding:error:'. Next, I have no idea how to load the txt back into my Array. Finally, I'd like to come up with a way to separate the arrays in the txt so that it remains editable, but that would be the absolute icing. Perhaps a solution would be to save each Object in an Array in a separate txt file and then load each txt into the array?

// GENERATE ARRAY

NoteBook = [[NSMutableArray alloc] init];

for (int temp = 0; temp < 3; temp++) {
    [NoteBook insertObject:@"Title\n\n Line1\nLine2..." atIndex:temp];
}

// SAVING MY MUTABLE ARRAY

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents directory

NSError *error;
BOOL succeed = [NoteBook writeToFile:[documentsDirectory stringByAppendingPathComponent:@"myfile.txt"]
                          atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (!succeed){
    // Handle error here
}



// LOADING TEXTFILE AND PUT IT INTO A MUTABLE ARRAY
// NO IDEA... how to do this
Code cracker
  • 3,105
  • 6
  • 37
  • 67
n.evermind
  • 11,944
  • 19
  • 78
  • 122

5 Answers5

3

Convert your arrays into strings, and vice versa, using, e.g.,

NSString* arrayText = [NoteBook componentsJoinedByString: @"<your-favourite-separator-string>"];

the write to file using [arrayText writeToFile...]

After reading a string back from a file, use

Notebook = [arrayText componentsSeparatedByString: @"<your-favourite-separator-string>"];

Lastly, don't do this. Save your array directly to a property list (read up on those) or JSON or some other structured data format.

Steven Kramer
  • 8,473
  • 2
  • 37
  • 43
  • Thanks for this. I haven't tried it, but it makes perfect sense theoretically. Why do you suggest that I should not do this, though? If my aim is to make editing the txt as easy as possible, why shouldn't I go for this and choose JSON instead? Also, you can't edit a plist very easily (if at all) with a text editor. – n.evermind Mar 22 '11 at 13:18
  • No, you're right. If readability comes into play, plain text wins out of course. – Steven Kramer Mar 22 '11 at 13:37
  • Hi, I just tried this and the first step works perfectly. However, when trying to read the information back into my program, there seems to be a conflict when trying to convert an array to the MutableArray NoteBook: `NoteBook = [tempTextOut componentsSeparatedByString: @"\n--- end of page ---\n"];` xCode tells me: Incompatible Objective-C types assigning 'struct NSArray*', expected 'struct NSMutableArray*'`. I guess this error message is quite clear, but I'm afraid I don't understand the problem here. I'd be very grateful if you could interpret the error message. Thanks!! – n.evermind Mar 23 '11 at 12:14
  • Just solved this with the help of others: http://stackoverflow.com/questions/5405328/convert-nsstring-into-nsmutablearray – n.evermind Mar 23 '11 at 12:57
2

Why not just turn the mutable array into JSON and write that string to a file? The inverse is to read the string from file and turn back into an array using the JSON parser. json-framework is very easy to use.

A benefit would be that you could create or modify your array by editing text files as long as you write valid JSON.

Adam Eberbach
  • 12,309
  • 6
  • 62
  • 114
  • Thanks for this suggestion, I'll have a closer look at JSON. But I guess I'd rather like to stick to a pure txt file without any formatting. I guess the only solution is to have a separate file for each object in the array. – n.evermind Mar 22 '11 at 12:33
  • You'll like JSON once you try it. It is very readable, less punctuation than XML for example. This is a good JSON validator for checking any that you write yourself or formatting it nicely: http://www.jsonlint.com/ – Adam Eberbach Mar 22 '11 at 12:39
2
  1. make NSMutableArray to NSArray .because NSMutableArray does not have writeToFile .
  2. retriev array from file

    NSArray *theCatalogInfo=nil;
    NSString *theCatalogFilePath = [NSString stringWithFormat:@"%@/Documents/",NSHomeDirectory()];
    theCatalogFilePath = [theCatalogFilePath stringByAppendingString:kCatalogCachePath];
    if(nil!=theCatalogFilePath)
    {
        theCatalogInfo=[[NSArray alloc]initWithContentsOfFile:theCatalogFilePath];
    }
    
  3. Save array To file

    NSString *theCatalogFilePath = [NSString stringWithFormat:@"%@/Documents/",NSHomeDirectory()];
    theCatalogFilePath = [theCatalogFilePath stringByAppendingString:kCatalogCachePath];
    
    [**YourArray** writeToFile:theCatalogFilePath atomically:YES];
    
Matthias Bauch
  • 89,811
  • 20
  • 225
  • 247
iOSPawan
  • 2,884
  • 2
  • 25
  • 50
  • 2
    NSMutableArray is a subclass of NSArray, and because of this NSMutableArray responds to `writeToFile:atomically:`. No need to create a NSArray. – Matthias Bauch Mar 22 '11 at 12:55
0

Have a look at following three methods to create a text file, write to it and read the data from it. The key is to store the different objects separated by space. And you should get it very simple.

-(void)createFile
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains
    (NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"Sample.txt"]; 

    NSFileManager * file_manager = [NSFileManager defaultManager];

    if(![file_manager fileExistsAtPath:filePath])
    {
        [file_manager createFileAtPath:filePath contents:nil attributes:nil];

        NSString *content = @"NULL NULL NULL";
        [content writeToFile:filePath 
                  atomically:NO 
                    encoding:NSStringEncodingConversionAllowLossy 
                       error:nil];
    }

}

-(void)writeToFile
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains
    (NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"Sample.txt"]; 

    NSString *content = [NSString stringWithFormat:@"%@ %@ %@", obj1, obj2, obj3];

    [content writeToFile:filePath 
                atomically:NO 
                encoding:NSStringEncodingConversionAllowLossy 
                error:nil];
}

-(void)readFromFile
{
    objects = [[NSArray alloc] init];
    NSArray *paths = NSSearchPathForDirectoriesInDomains
    (NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"Sample.txt"]; 
    if (filePath) {  
        NSString *myText = [NSString stringWithContentsOfFile:filePath encoding:NSASCIIStringEncoding error:nil];  
        if (myText) { 
            objects = [myText componentsSeparatedByString:@" "];
        }
    }

}
Vaibhav Tekam
  • 2,344
  • 3
  • 18
  • 27
  • `NSStringEncodingConversionAllowLossy` is not a valid encoding. `createFile` is a useless method if you overwrite the file in `writeToFile`. `createFileAtPath:contents:attributes:` is superfluous if you create another file in the next line. And you leak the old object in the first and last line of `readFromFile`. And nobody uses ascii these days. – Matthias Bauch Mar 22 '11 at 12:48
  • @fluchtpunkt: ooops... it looked, in my very inexperienced eyes, as a rather structured reply. – n.evermind Mar 22 '11 at 13:00
0

if your nsarray contains nsdictionary, nsarray, nsstring, nsnumber, nsdata or nsdate objects (no custom objects, int's, etc) you can simply write the contents of your mutable array to a plist file.

this will maintain the data structure you have and you can simply read that data right into an array. How I do it in a couple of my data classes is

NSArray *tempArray = [NSArray arrayWithContentsOfFile:[Utils getFileLocation]];
if (tempArray == nil) {
    yourArray = [[NSMutableArray alloc] init];
} else {
    yourArray = [[NSArray deepMutableCopy:tempArray] retain];
}
Nathan Jones
  • 1,836
  • 14
  • 13