How to write a String in different lines to a .txt file on iOS - ios

I am trying to write a string to a t.t file in the documents folder of my app. I can write the string to it, but when I write another string to the file it overwrites the other string, is it possible to write more strings to a text files, with a blank line between strings, many in this formate
String
String
Strine
…
I am using this code to write the string to an text file, it works for one string, but not for multible strings.
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:#"%#/Barcodedata.txt",
documentsDirectory];
//create content - four lines of text
NSString *content = [NSString stringWithFormat:#"%#",sym.data];
//save content to the documents directory
[content writeToFile:fileName
atomically:NO
encoding:NSStringEncodingConversionAllowLossy
error:nil];

There's a few ways to do this, depending on how you implemented your code.
One way would be to load up the original .txt file into a NSMutableString object and then append that new line to the end of the string and re-write out the file (this isn't super efficient, especially as you start appending after 1000 strings, 100 strings, 50 strings, etc.)
Or you could use the low level C function "fwrite" with the append bit set.
Edited:
Since you want to see code, here's how to do it with my first suggestion:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:#"%#/Barcodedata.txt", documentsDirectory];
//create content - four lines of text
NSError * error = NULL;
NSStringEncoding encoding;
NSMutableString * content = [[NSMutableString alloc] initWithContentsOfFile: fileName usedEncoding: &encoding error: &error];
if(content == NULL)
{
// if the file doesn't exist yet, we create a mutable string
content = [[NSMutableString alloc] init];
}
if(content)
{
[content appendFormat: #"%#", sym.data];
//save content to the documents directory
BOOL success = [content writeToFile:fileName
atomically:NO
encoding:NSStringEncodingConversionAllowLossy
error:&error];
if(success == NO)
{
NSLog( #"couldn't write out file to %#, error is %#", fileName, [error localizedDescription]);
}
}

Related

How do i save multiple strings and not overwrite while writing to a plist file in iOS?

I'm using a "facts.plist" to display a fact(string) after pressing a button, i have a button there that writes that string to a "favourites.txt" file and there i can use it for future use.
Here is the code for that:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:#"MyFavorites.txt"];
//documentsDirectory];
[self.displayJoke.text writeToFile:fileName
atomically:NO
encoding:NSStringEncodingConversionAllowLossy
error:nil];
NSError *error;
NSString *str = [NSString stringWithContentsOfFile:fileName encoding:NSUTF8StringEncoding error:&error];
NSLog(#"%#", str);
But every time I tap that button the previous string gets overwritten with the new string. How do i create a dictionary or Array to prevent this?
every time i tap that button the previous string gets overwritten with the new string
It doesn't "get overwritten". You are overwriting it:
[self.displayJoke.text writeToFile:fileName
atomically:NO
encoding:NSStringEncodingConversionAllowLossy
error:nil];
That line replaces the file fileName with a new file. If that's not what you want to do, then don't do that. If you want to include the existing contents of the file, it's up to you to read the file first and include that in what you write. (Alternatively, you could look into NSFileHandle, which allows you to append to a file.)

Proper way to giving name to file when [NSData writeToFile:] used

I'm using that code to save downloaded videos from internet to application document folder:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *save_it = [documentsDirectory stringByAppendingPathComponent:video_filename];
NSError *error;
BOOL success = [fileData writeToFile:save_it options:0 error:&error];
if (!success) {
NSLog(#"writeToFile failed with error %#", error);
}
it works, but if there is a slash "/" in the video_filename it breaks because of slash is directory seperator, I know.
For example when video_filename is : Best Video / Best Song Ever.3gpp , log says:
{NSFilePath=/Users/Apple/Library/Developer/CoreSimulator/Devices/5A7D36F5-6EDB-495D-9E8E-B9EB22E5357C/data/Containers/Data/Application/B1D0AC48-D84C-4A0D-9F09-08BF4C45DD32/Documents/Best Video / Best Song Ever.3gpp, NSUnderlyingError=0x7d339430 "The operation couldn’t be completed. No such file or directory"}
I don't know is there any other special character that will make crashing,
So what is the best way of cleaning these special characters from nsstring ?
We can make SEO friendly urls in PHP, I'm searching a function like that to do this.
The first problem I see here is that your file path includes some spaces. in the example you gave, the value of video_filename variable is "Best Video / Best Song Ever.3gpp" which includes spaces around the slash. You first have to delete the spaces, this might help you do that:
NSArray *components = [video_filename componentsSeparatedByString:#"/"];
for (NSInteger i = 0, i < components.count, ++i) {
NSString *string = components[i];
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
components[i] = string;
}
NSString *path = [components componentsJoinedByString:#"/"];
If I understood correctly, your video_filename might be either in the form xxx.3gpp or yyy/xxx.3gpp. If it's the format of yyyy/xxxx.3gpp, you first have to create a directory named yyyy and then save the file to that directory.
This might help you do that:
- (void)createDirectory:(NSString *)directoryName
atFilePath:(NSString *)filePath
{
NSString *filePathAndDir = [filePath
stringByAppendingPathComponent:directoryName];
NSError *error;
if (![[NSFileManager defaultManager] createDirectoryAtPath:filePathAndDir
withIntermediateDirectories:NO
attributes:nil
error:&error]) {
NSLog(#"Create directory error: %#", error);
}
}
and the way you would use this is
[self createDirectory:components[0] atFilePath:documentsDirectory];
hope this helps!
So if your filename is actually "Best Video / Best Song Ever.3gpp" I am sorry but nothing easy comes to mind.
Now if Best Video is a folder where you will save your file you can use :
+(NSString*) getPathToFolder:(NSString*) folderName {
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *folderPath = [documentsPath stringByAppendingPathComponent:folderName];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:folderPath]) {
NSLog(#"Creating a new folder at\n%#", folderPath) ;
[fileManager createDirectoryAtPath:folderPath withIntermediateDirectories:NO attributes:nil error:nil];
}
return folderPath ;
}
This will check if your folder exist or not, if it does not exists then it will create it.
it will return the path you will want to use to save your file.
Now regarding the naming of the files, using spaces is highly unadvisable, I suggest using :
NSString* pathWITHSpaces ;
NSString* pathWithoutSpaces = [pathWITHSpaces stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
Hope this helps a bit

Need to get an XML from server encoded in windows-1252 for my iOS application

I have an iOS application which is download from server an XML file encoded in Windows 1252.
I am using the following code to save it to my document folder :
NSString *path = #"http://server/file.xml";
NSURL *URL = [NSURL URLWithString:[path stringByAddingPercentEscapesUsingEncoding:NSWindowsCP1252StringEncoding]];
NSData *xmlData = [NSData dataWithContentsOfURL:URL];
if(xmlData == nil) {
// Error - handle appropriately
NSLog(#"ERROR");
}
NSString *applicationDocumentsDir=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *storePath=[applicationDocumentsDir stringByAppendingPathComponent:#"annonces.xml"];
[xmlData writeToFile:storePath atomically:TRUE];
NSLog(#"write xml");
It doesn't work, I've got an nil response when I try to read it with the parser. How could I do to get it properly. I cannot change the encoding of te xml which is on the server. If I change the XML encoding manually, I've got a correct response.
This is how I pass the XML string to parse it with XML Dictionnary class :
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *finalPath = [path stringByAppendingPathComponent:#"annonces.xml"];
NSString *string = [[NSString alloc] initWithContentsOfFile:finalPath encoding:NSWindowsCP1252StringEncoding error:NULL];
NSLog(#"string: %#", string);
NSDictionary *items = [NSDictionary dictionaryWithXMLString:string];
NSLog(#"dictionary: %#", items);
Your URL variable contains the url address of the location of the XML file you want to download.
However you are applying NSWindowsCP1252StringEncoding to the url, not to the content of the file.
xmlData is nil because dataWithContentsOfURL: cannot find the file at the location you have specified within URL.
You need to download the file first, then once its downloaded then you can be concerned about what encoding its in and how to parse it.
The way you are using NSWindowsCP1252StringEncoding has got nothing to do with the content of the file.

writing string to txt file in objective c

Pulling my hair out trying to work this out. i want to read and write a list of numbers to a txt file within my project. however [string writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error] doesnt appear to write anything to the file. I can see there is the path string returns a file path so it seems to have found it, but just doesnt appear to write anything to the file.
+(void)WriteProductIdToWishList:(NSNumber*)productId {
for (NSString* s in [self GetProductsFromWishList]) {
if([s isEqualToString:[productId stringValue]]) {
//exists already
return;
}
}
NSString *string = [NSString stringWithFormat:#"%#:",productId]; // your string
NSString *path = [[NSBundle mainBundle] pathForResource:#"WishList" ofType:#"txt"];
NSError *error = nil;
[string writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error];
NSLog(#"%#", error.localizedFailureReason);
// path to your .txt file
// Open output file in append mode:
}
EDIT: path shows as /var/mobile/Applications/CFC1ECEC-2A3D-457D-8BDF-639B79B13429/newAR.app/WishList.txt so does exist. But reading it back with:
NSString *path = [[NSBundle mainBundle] pathForResource:#"WishList" ofType:#"txt"];
returns nothing but an empty string.
You're trying to write to a location that is inside your application bundle, which cannot be modified as the bundle is read-only. You need to find a location (in your application's sandbox) that is writeable, and then you'll get the behavior you expect when you call string:WriteToFile:.
Often an application will read a resource from the bundle the first time it's run, copy said file to a suitable location (try the documents folder or temporary folder), and then proceed to modify the file.
So, for example, something along these lines:
// Path for original file in bundle..
NSString *originalPath = [[NSBundle mainBundle] pathForResource:#"WishList" ofType:#"txt"];
NSURL *originalURL = [NSURL URLWithString:originalPath];
// Destination for file that is writeable
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSURL *documentsURL = [NSURL URLWithString:documentsDirectory];
NSString *fileNameComponent = [[originalPath pathComponents] lastObject];
NSURL *destinationURL = [documentsURL URLByAppendingPathComponent:fileNameComponent];
// Copy file to new location
NSError *anError;
[[NSFileManager defaultManager] copyItemAtURL:originalURL
toURL:destinationURL
error:&anError];
// Now you can write to the file....
NSString *string = [NSString stringWithFormat:#"%#:", yourString];
NSError *writeError = nil;
[string writeToFile:destinationURL atomically:YES encoding:NSUTF8StringEncoding error:&error];
NSLog(#"%#", writeError.localizedFailureReason);
Moving forward (assuming you want to continue to modify the file over time), you'll need to evaluate if the file already exists in the user's document folder, making sure to only copy the file from the bundle when required (otherwise you'll overwrite your modified file with the original bundle copy every time).
To escape from all the hassle with writing to a file in a specific directory, use the NSUserDefaults class to store/retrieve a key-value pair. That way you'd still have hair when you're 64.

IOS: problem to synchronize nsarray with string

I have a NSArray in this way
myArray[0] = [string1, string2, string3, string4, mySecondArray, string5]; (at 0 position)
I write this array inside a txt file in this way
NSString *outputString = #"";
for (int i = 0; i< myArray.count; i++){
outputString = [outputString stringByAppendingString:[[[myArray objectAtIndex:i ] componentsJoinedByString:#"#"] stringByAppendingString:#";"]];
}
NSLog(#"string to write = %#", outputString);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"Text.txt"];
NSError *error;
[outputString writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
then the result of NSLog is = (position 0 of myArray) (mySecond array is empty)
one#two#three#four#(
)#five;
I want to know:
Why the array wrap?
When I'll go to read this string how can I know that it's mySecondArray?
When you message componentsJoinedByString: on an NSArray object, it calls description on each of its objects and concatenates them in order. For NSString objects, they are the strings themselves. The array wraps because of the way the description method has been implemented.
As for identifying the array while you are reading the string back, I don't think it is possible. You should consider writing the array to the file rather i.e.
[[myArray objectAtIndex:0] writeToFile:filePath atomically:YES];
or
[myArray writeToFile:filePath atomically:YES];
depending on the requirement. This way you will be able to read the elements back properly.

Resources