String Programming Guide 2
String Format Specifiers
Format Specifiers
IEEE printf specification:
PlatForm Dependencies
直接用 ld 代替 d, 但是要区分 float(f) 和 double(lf)
Reading Strings From and Writing Strings To Files and URLS
Reading From Files and URLs
1.知道编码方式的时候:
//这个例子写不出来,以后再回来填坑,,,如果我还记得的话 NSURL *URL = ...; NSError *error; NSString *stringFromFileAtURL = [[NSString alloc]initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error]; if (stringFromFileAtURL == nil){ //an error occurred NSLog(@"Error reading file at %@\n%@", URL, [error localizedFailureReason]); //implementation continues...
也可以通过 NSData 来读入字符串,然而也要指定编码方式:
NSURL *URL = ...; NSData *data = [NSData dataWithContentsOfURL: URL]; //假设编码是 UTF8 NSString *string = [NSString stringWithUTF8String:[data bytes]]; //如果编码是ISO-8859-1 NSString *string = [[NSString alloc] initWithData data encoding: NSISOLatin1StringEncoding];
2.不知道编码方式的时候:
a. 尝试使用 stringWithContentsOfFile:usedEncoding:error: 或者 initWithContentsOfFile:usedingEncoding:error:(还有其他基于 URL 的方法也可以)
b.如果 a 不行的话,尝试 UTF-8
c.如果 b 也不行的话,调查下数据源看看哪些比较有可能. 如 windows/ISO 的 Latin 1
d.尝试使用NSAttributedString的加载方法(如initWithURL:options:documentAttributes:error:)
Writing to Files and URLs
使用writeToFile:atomically:encoding:error:或者writeToURL:atomically:encoding:error:方法
这里又是一个我暂时没有办法自己写的坑
NSURL *URL = ...; NSString *string = ...; NSError *error; BOOL ok = [string writeToURL:URL atomically:YES encoding:NSUnicodeStringEncoding error:&error]; if (!ok) { //an error occurred NSLog(@"Error writing file at %@\n%@", path, [error localozedFailureReason]); //implementation continues ...
小结
Source | Creation Method | Extraction Method |
URL contens | stringWithContentsOfURL:encoding:error: stringWithContentsOfURL:usedEncoding:error: | writeToURL:atomically:encoding:error: |
File contents | stringWithContentsOfFile:encoding:error stringWithContentsOfFile:usedEncoding:error: | writeToFile:atomically:encoding:error: |
Searching, Comparing, and Sorting Strings
Search and Comparison Methods
Searching strings
rangeOfString:...方法传入 NSString 作为搜索参数
rangeOfCharacterFromSet:... 方法传入一个字符串集合作为搜索参数.
都是返回找到的第一个位置的 NSRange 没有找到则返回{NSNotFound, 0}
如果只是想知道是否包含某字符串, 可以直接这样用:(坑)
BOOL match = [myPredicate evaluateWithObject: aString];
Comparing and sorting strings
compare:...方法返回比较对象的大小排序关系
compare:options:range:
compare:options:
compare:options:range:locale:
options参数可以传入很多已经定好了的搜索规则可以直接使用
注意:对于直接呈现给用户看的排序结果, 一定要填写 locale 选项. 直接使用 localizedCompare: 或 localizedCaseInsensitiveCompare:也可以
如果需要像 Finder 一样排序的话,需要使用 compare:options:range:locale:,其中 options 参数传入:NSCaseInsensitiveCompare, NSNumberSearch, NSWidthInsensitiveSearch, NSForcedOrderingSearch(后面一点有例子)
Search and Comparison Options
Examples
Case-Insensitive Search for Prefix and suffix:
NSString中的 hasPreFix:和hasSuffix:方法可以用来搜索前缀后缀:
NSString *searchString = @"age"; NSString *beginsTest = @"Agencies"; NSRange prefixRange = [beginsTest rangeOfString:searchString options:(NSAnchoredSearch|NSCaseInsensitiveSearch)]; NSLog(@"{%lu,%lu}",prefixRange.location,prefixRange.length); //OUTPUT: 2015-06-10 19:28:24.674 XYZPersonTest[1049:94971] {0,3} NSString *endsTest = @"BRICOLAGE"; NSRange suffixRange = [endsTest rangeOfString:searchString options:(NSCaseInsensitiveSearch|NSAnchoredSearch|NSBackwardsSearch)]; NSLog(@"{%lu,%lu}",suffixRange.location,suffixRange.length); //OUTPUT: 2015-06-10 19:30:10.596 XYZPersonTest[1058:95376] {6,3}
Comparing Strings:
基本形式
NSString *string1 = @"string1"; NSString *string2 = @"string2"; NSComparisonResult result; result = [string1 compare:string2]; NSLog(@"%ld",result); //OUTPUT: 2015-06-10 19:35:11.491 XYZPersonTest[1074:96680] -1(NSOrderedAscending)
加上 NSNumericSearch option(把数字组合起来再做数值上大小的比较)
NSString *string10 = @"string10"; NSString *string2 = @"string2"; NSComparisonResult result; result = [string10 compare:string2]; NSLog(@"%lu",result); //OUTPUT: 2015-06-10 19:40:59.793 XYZPersonTest[1114:98253] 18446744073709551615(什么鬼!本来应该是-1 NSOrderedAscending才对的) result = [string10 compare:string2 options:NSNumericSearch]; NSLog(@"%lu",result); //OUTPUT: 2015-06-10 19:40:59.794 XYZPersonTest[1114:98253] 1(NSOrderedDescending) result = [string10 compare:string10]; NSLog(@"%lu",result); //OUTPUT: 2015-06-10 19:40:59.794 XYZPersonTest[1114:98253] 1(NSOrderedSame)
你也可以直接使用caseInsensitiveCompare:和localizedCaseInsensitiveCompare:来实现不区分字母大小的比较
NSString *string_a = @"Arvdvard"; NSString *string_A = @"ARVDVARD"; NSComparisonResult result; result = [string_a compare:string_A]; NSLog(@"%lu",result); //OUTPUT:2015-06-10 19:48:30.923 XYZPersonTest[1139:100733] 1(NSOrderedDescending) result = [string_a caseInsensitiveCompare:string_A]; NSLog(@"%lu",result); //OUTPUT:2015-06-10 19:48:30.924 XYZPersonTest[1139:100733] 0(NSOrderedSame) //same to result = [string_a compare: string_A options:NSCaseInsensitiveSearch];
Sorting strings like Finder
OS X v10.6及以后的版本里面, Finder 使用 localizedStandardCompare: 方法来实现文件排序.
int finderSortWithLocale(id string1, id string2, void *locale){ static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch|NSNumericSearch|NSWidthInsensitiveSearch|NSForcedOrderingSearch; NSRange string1Range = NSMakeRange(0, [string1 length]); return [string1 compare:string2 options:comparisonOptions range:string1Range locale:(NSLocale *)locale]; }
使用sortedArrayUsingFunction:context:方法调用上面比较函数
NSArray *stringArray = @[@"string 1",@"String 21",@"string 12",@"string 11", @"String 02"]; NSArray *sortedArray = [stringArray sortedArrayUsingFunction:finderSortedWithLocale context:[NSLocale currentLocale]]; //sortedArray:{"string 1", "String 02", "String 11", "string 12", "String 21"}
Words, Paragraphs, and Line Breaks
Word Boundaries
分词可以参考Unicode Standard Annex #29
苹果还自己加了一些本地化语言扩展
然而我们并不能修改这些规则
cocoa 框架里面中有一些函数会用到这些规则,如:NSAttributedString中doubleClickAtIndex:和nextWordFromIndex:forward:
(都没有用过,猜测是只双击自动选中光标附近的某些词)
Line and Paragraph Separator Characters
Cocoa框架定义了换行和分段符
const | unicode | |
换行符 | NSLineSeparatorCharacter | U+2028 |
分段符 | NSParagraphSeparatorCharacter | U+2029 |
一些系统识别换行分段符号的字符(应该):
POSIX-level:\n
旧macintosh 软件:\r
windows:\r\n
Cocoa 框架把上面的符号都当成是分段符NSParagraphSeparatorCharacter,例如方法insertNewline会插入\n(cocoa 默认就插\n)
而分行符NSLineSeparatorCharacter只有在特定的环境中才会有意义?例如 html<br>
Separating a String "by Paragraph"
如果确定平台的分行符\分段符
可以直接使用
NSString *myString = @"123\n456\n789\n10"; NSArray *arr = [myString componentsSeparatedByString:@"\n"]; NSLog(@"%@",arr); /* OUTPUT: 2015-06-10 20:33:27.104 XYZPersonTest[1174:109738] ( 123, 456, 789, 10 ) */
为了适应多种系统使用不同的分行\分段符,可以这样干:
NSString *myString = @"123\n456\n789\n10\r11\r\n12"; unsigned length = [myString length]; unsigned paraStart = 0, paraEnd = 0, contentsEnd = 0; NSMutableArray *array = [NSMutableArray array]; NSRange currentRange; while (paraEnd < length) { [myString getParagraphStart:¶Start end:¶End contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; currentRange = NSMakeRange(paraStart, contentsEnd-paraStart); [array addObject:[myString substringWithRange:currentRange]]; } NSLog(@"%@",array);
Characters and Grapheme Clusters
NSString 内部使用的时 UTF-16编码
然后有些语言的字符需要使用两个 UTF-16组合才能表示,不过这个 NSString 会自己解决
在这种情况下需要对这些 string 对象操作,需要使用:
rangeOfComposedCharacterSequencesForRange:
rangeOfComposedCharacterSequenceAtIndex:
等方法来操作
尽量使用 NSString 自带的方法来处理字符串, 他们会很大程度上帮我们处理好这些组合字符:
lowercaseString
uppercaseString
capitalizedString
rangeOfString
rangeOfCharacterFromSet
等
如果cocoa 框架没有办法满♂足需求,可以参考 Unicode Standard Annex #29 寻找解决方法?
在 OS X v10.5及之后的系统, NSLayoutManager API 允许在文本内容任何地方插入字符,包括上述的组合字符串
参考:Cocoa Text Architecture Guide