I have a txt file with some URLs like this
http://url1.com
http://url1.com
http://url1.com
Separated by a line break. How could I add those as different entries separated by line breaks to an NSMutableArray? Thanks :)
Try something like this:
NSMutableArray *txtLines = [NSMutableArray array];
[txtFile enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
if ([line length] > 0) {
[txtLines addObject:line];
}
}];
Update
#Evan is right, the above only works if blocks are available on your platform. A compiler directive around that code should take care of this limitation, e.g.:
#if NS_BLOCKS_AVAILABLE
// iOS 4.0+ solution
#else
// iOS 2.0+ solution
#endif
NSString *myListString = /* load / download file */
NSMutableArray *myList = [myListString componentsSeparatedByString:#"\n"];
You may have to use <br/> if it's HTML.
#octy's solution is only available in iOS 4.0 or later. This solution is iOS 2.0 or later. You can check the iOS version and choose which one to use:
BOOL useEnumeratedLineParsing = FALSE;
NSString *reqSysVer = #"4.0";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
useEnumeratedLineParsing = TRUE;
Then check the value of useEnumeratedLineParsing.
NSString *textFilePath = [[NSBundle mainBundle] pathForResource:#"urls" ofType:#"txt"];
NSString *fileContentsUrls = [NSString stringWithContentsOfFile:textFilePath encoding:NSUTF8StringEncoding error:nil];
NSArray *myArray = [urls componentsSeparatedByString:#"\n"];
As long as it isn't mega-large, you could read the whole file into an NSString.
NSString *text = [NSString stringWithContentsOfFile:path encoding:NSUTF8Encoding error:nil];
Then split the lines:
NSArray *lines = [text componentsSeparatedByString:#"\n"];
And make it mutable:
NSMutableArray *mutableLines = [lines mutableCopy];
Now, depending on where your text file is coming from, you probably need to be more careful. It could be separated by \r\n instead of just \n, in which case your lines will contain a bunch of extra \r characters. You could clean this up after the fact, using something to remove extra whitespace (your file also might have blank lines which the above will turn into empty strings).
On the other hand, if you're in control of the file, you won't have to worry about that. (But in that case, why not read a plist instead parsing a plain text file...)
Related
I am kind of new to iOS development.
I want to retrieve strings from the text(.rtf) file I have. The file is within my application main bundle. It's content are:
#start word1 First word end word2 Second word end //lots of things to be added later
Code:
path = [[NSBundle mainBundle]pathForResource:#"words" ofType:#"rtf"];
if(path)
{
NSLog(#"path exists");
}
NSError *error = nil;
NSString *file = [[NSString alloc]initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
if(error)
{
NSLog(#"error");
}
NSString *finalword= [[NSString alloc]init ];
NSString *startfrom = [[NSString alloc] initWithFormat:#"word%i",i+1];
i++;
NSLog(#"%#",startfrom);
NSString *wordoftheday = [[NSString alloc]init ];
NSScanner *scanner = [NSScanner scannerWithString:file];
[scanner scanUpToString:startfrom intoString:nil];
[scanner scanUpToString:#"end" intoString:&wordoftheday];
finalword = [wordoftheday substringFromIndex:[startfrom length]];
NSLog(#"%#",finalword);
Word.text = final word; //change label text
//[final word release];
//[wordoftheday release];
//[file release];
Code is working fine but it leaves me with memory management issues. App crashes if I release the variables in the last commented code.
Also this method is in my viewdidload. I want the label to change text when user click a button. I will have to write the same code again in that method which leaves me with more memory issue.
So looking at these one by one, focusing on the memory issues and not the overall strategy here:
NSString *finalword= [[NSString alloc]init ];
Here you alloc/init a new immutable and empty NSString, and then you end up overwriting the pointer to this later anyway. You should just delete this line. And then you'll need to move the declaration down a few lines to this:
NSString *finalword = [wordoftheday substringFromIndex:[startfrom length]];
Then you have:
NSString *startfrom = [[NSString alloc] initWithFormat:#"word%i",i+1];
This one you need to release later. Or just change it to:
NSString *startfrom = [NSString stringWithFormat:#"word%i",i+1];
Then you have:
NSString *wordoftheday = [[NSString alloc]init ];
Same story as finalword. Except that you do need to define this variable so you can pass it to the scanner later. So change it to:
NSString *wordoftheday = nil;
And lastly, you can release 'file'. That is fine. But you don't want to release 'wordoftheday' or 'finalword' because you don't own those strings. You did not create them yourself.
And one other note:
if(error)
That is not the correct way to check for an error in loading 'file'. You should check the return from the method and then look for an error if and only if the return value was nil. So change that line to:
if(!file)
(OK, that wasn't really a memory issue, but a bug I did notice.)
I think that's all of it at least as far as memory issues. I hope that helps.
make those variables as member variables and release in the dealloc
i am trying to parse a text file saved in doc dir below show is the code for it
NSArray *filePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *docDirPath=[filePaths objectAtIndex:0];
NSString *filePath=[docDirPath stringByAppendingPathComponent:#"SKU.txt"];
NSError *error;
NSString *fileContents=[NSString stringWithContentsOfFile:filePath];
NSLog(#"fileContents---%#",fileContents);
if(!fileContents)
NSLog(#"error in reading file----%#",error);
NSArray *values=[fileContents componentsSeparatedByString:#"\n"];
NSLog(#"values-----%#",values);
NSMutableArray *parsedValues=[[NSMutableArray alloc]init];
for(int i=0;i<[values count];i++){
NSString *lineStr=[values objectAtIndex:i];
NSLog(#"linestr---%#",lineStr);
NSMutableDictionary *valuesDic=[[NSMutableDictionary alloc]init];
NSArray *seperatedValues=[[NSArray alloc]init];
seperatedValues=[lineStr componentsSeparatedByString:#","];
NSLog(#"seperatedvalues---%#",seperatedValues);
[valuesDic setObject:seperatedValues forKey:[seperatedValues objectAtIndex:0]];
NSLog(#"valuesDic---%#",valuesDic);
[parsedValues addObject:valuesDic];
[seperatedValues release];
[valuesDic release];
}
NSLog(#"parsedValues----%#",parsedValues);
NSMutableDictionary *result;
result=[parsedValues objectAtIndex:1];
NSLog(#"res----%#",[result objectForKey:#"WALM-FT"]);
The problem what i am facing is when i try to print lineStr ie the data of the text file it is printing as a single string so i could not able to get the contents in line by line way please help me solve this issue.
Instead use:
- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator
it covers several different newline characters.
Example:
NSArray *values = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
for (NSString *lineStr in values) {
// Parsing code here
}
ALso seperatedValues is over released. First one is created with alloc init, then on the next line it is replaced by the method componentsSeparatedByString. So the first one od lost without being released, that is a leak. Later the seperatedValues created by componentsSeparatedByString is released but it is already auto released by componentsSeparatedByString to that is an over release;
Solve all the retain/release/autorelease problem with ARC (Automatic Reference Counting).
Here is a version that uses convenience methods and omits over release:
NSArray *values = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
for (NSString *lineStr in values) {
NSArray *seperatedValues = [lineStr componentsSeparatedByString:#","];
NSString *key = [seperatedValues objectAtIndex:0];
NSDictionary *valuesDic = [NSDictionary dictionaryWithObject:seperatedValues forKey:key];
[parsedValues addObject:valuesDic];
}
NSLog(#"parsedValues---%#",parsedValues);
Are you sure the line separator used in your text file is \n and not \r (or \r\n)?
The problem may come from this, explaining why you don't manage to split the files into different lines.
I would like to know how to selectively trim an NSMutableString. For example, if my string is "MobileSafari_2011-09-10-155814_Jareds-iPhone.plist", how would I programatically trim off everything except the word "MobileSafari"?
Note : Given the term programatically above, I expect the solution to work even if the word "MobileSafari" is changed to "Youtube" for example, or the word "Jared's-iPhone" is changed to "Angela's-iPhone".
Any help is very much appreciated!
Given that you always need to extract the character upto the first underscore; use the following method;
NSArray *stringParts = [yourString componentsSeparatedByString:#"_"];
The first object in the array would be the extracted part you need I would think.
TESTED CODE: 100% WORKS
NSString *inputString=#"MobileSafari_2011-09-10-155814_Jareds-iPhone.plist";
NSArray *array= [inputString componentsSeparatedByString:#"_"];
if ([array count]>0) {
NSString *resultedString=[array objectAtIndex:0];
NSLog(#" resultedString IS - %#",resultedString);
}
OUTPUT:
resultedString IS - MobileSafari
If you know the format of the string is always like that, it can be easy.
Just use NSString's componentsSeparatedByString: documented here.
In your case you could do this:
NSString *source = #"MobileSafari_2011-09-10-155814_Jareds-iPhone.plist";
NSArray *seperatedSubStrings = [source componentsSeparatedByString:#"_"];
NSString *result = [seperatedSubStrings objectAtIndex:0];
#"MobileSafari" would be at index 0, #"2011-09-10-155814" at index 1, and #"Jareds-iPhone.plist" and at index 2.
Try this :
NSString *strComplete = #"MobileSafari_2011-09-10-155814_Jareds-iPhone.plist";
NSArray *arr = [strComplete componentsSeparatedByString:#"_"];
NSString *str1 = [arr objectAtIndex:0];
NSString *str2 = [arr objectAtIndex:1];
NSString *str3 = [arr objectAtIndex:2];
str1 is the required string.
Even if you change MobileSafari to youtube it will work.
So you'll need an NSString variable that'll hold the beginning of the string you want to truncate. After that one way could be to change the string and the variable string values at the simultanously. Say, teh Variable string was "Youtube" not it is changed to "MobileSafari" then the mutable string string should change from "MobileSafari_....." to "YouTube_......". And then you can get the variable strings length and used the following code to truncate the the mutable string.
NSString *beginningOfTheStr;
.....
theMutableStr=[theMutableStr substringToIndex:[beginningOfTheStrlength-1]];
See if tis works for you.
I have a text file like this
question1
question2
question3
I want to read only the first line into a nsstring
after that I want to mark the first line so the next time, skip the first line, but I don't know how to do it, I have this code for read but give me only the third line
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"qa" ofType:#"txt"];
NSString *myText = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSArray *lines = [myText componentsSeparatedByString:#"\n"];
for(myText in lines)
{
texview.text = myText;
}
}
Ok I try this code, Do not work, what I am Doing wrong?
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString * const kKey = #"OneTimeKey";
NSObject *keyValue = [defaults objectForKey:kKey];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"qa" ofType:#"txt"];
NSString *myText = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSArray *lines = [myText componentsSeparatedByString:#"|"];
if (keyValue==nil) {
for(myText in lines)
{
preguntadia.text = myText;
[defaults setBool:YES forKey:kKey];
}
}
The problem is that your "for" is executed really fast, so fast that you can only see when the last element of the array is set to your text view.
What you can do is have a variable which specifies which one of the strings to show next and, with a timer, set a different string on your text view every number of seconds, so you can actually see the changes.
Bonus, you can make it cycle with something like this:
-(void)updateText{
[textView setText:[lines objectAtIndex:currentIndex]];
currentIndex++;
currentIndex = currentIndex % [lines count];
}
So when it reaches the last string, it shows the first again.
You'll need to store a line counter locally to keep track, I think. That is easily accomplished with something like this to save:
[[NSUserDefaults standardDefaults] setInteger:lineCount forKey:#"lineCountKey"];
and fetch:
int lineCount = [[NSUserDefaults standardDefaults] integerForKey:#"lineCountKey"];
and then just read and discard lineCount lines when you open the file.
Now, splitting the line you want into multiple pieces, you can use the NSString method componentsSeparatedByString:, but be careful. If your "questions" are actually multi-word questions, you'll need to pick a separator other than space. Vertical bar (|) might be a good choice, then you can do something like this:
NSArray *questions = [line componentsSeparatedByString:#"|"];
NB: Code typed from memory; not compiled. :-)
I need to parse a text file, one line at a time. Also, is there EOF in Objective-C?
Something like this might work for you:
NSString *fileContents = [NSString stringWithContentsOfFile:#"myfile.txt"];
NSArray *lines = [fileContents componentsSeparatedByString:#"\n"];
This will give you an array where each element is a line of the string.
Objective-C is a proper extension of C. Any C program is a valid Objective-C program. Among other things, this means that EOF defined in the standard C header "stdio.h" is an EOF marker in Objective-C as well.
stringWithContentsOfFile is deprecated.
Here is an updated answer:
NSError* error;
NSString *fileContent = [NSString stringWithContentsOfFile:txtFilePath encoding:NSUTF8StringEncoding error:&error];
NSArray *lines = [fileContent componentsSeparatedByString:#"\n"];