2013-03-01 45 views
19

我從csv文件中讀取,並且想要使用stringWithContentsOfFile(它是一個多行字符串)和單獨的行代表csv文件中的行來拆分所獲得的長字符串。我該怎麼做呢?如何用換行符分割字符串

+0

爲什麼要將整個文件加載到內存中?這不會幫助你的記憶足跡... – trojanfoe 2013-03-01 11:44:51

+0

也許已知文件不會那麼大。它*只是文本... – uchuugaka 2013-03-02 09:38:01

+0

是的...文件足夠小...它只有54行和4列! – 2013-03-03 03:36:41

回答

26

您可以將字符串分解爲字符串數組,然後根據需要進行操作。

NSArray *brokenByLines=[yourString componentsSeparatedByString:@"\n"] 
+5

這使得很多關於行分隔符是什麼的假設。 – uchuugaka 2013-03-02 09:38:28

+1

如果您不知道分隔符是什麼:'let lines = stringData.stringByReplacingOccurrencesOfString(「\ r \ n」,withString:「\」n「)。stringByReplacingOccurrencesOfString(」\ r「,withString:」\ n「 ).componentsSeparatedByString(「\ n」)' – Zaphod 2016-04-02 14:25:43

+0

如果字符串用newLineCharacterSet分隔,則不需要替換@「\ r」; – 2016-09-12 20:58:15

2

您需要將您的內容與「\ n」分開。

NSString *str= [NSString stringWithContentsOfFile:filePathLib encoding:NSUTF8StringEncoding error:nil]; 
    NSArray *rows = [str componentsSeparatedByString:@"\n"]; 

    for(int i =0;i<[rows count];i++) 
     NSLog(@"Row %d: %@",i,[rows objectAtIndex:i]); 
+1

這也對分隔符做出了假設 – uchuugaka 2013-03-02 09:39:24

37

只是爲了防止任何人像我一樣絆倒這個問題。這將與任何換行符工作:

NSCharacterSet *separator = [NSCharacterSet newlineCharacterSet]; 
NSArray *rows = [yourString componentsSeparatedByCharactersInSet:separator]; 
+0

即使對CSV文件也適用...其中「\ n」不會 – DogCoffee 2015-04-28 06:05:03

+3

如果行分隔符是「\ r \ n」(兩個字符),則會在Windows格式的文件中產生空字符串。 – Suragch 2015-08-15 03:31:36

13

你應該知道,\n不是用來分割出一個新行的唯一字符。例如,如果文件保存在Windows中,則換行符將爲\r\n。閱讀the Newline article in Wikipedia瞭解更多關於這方面的信息。

因此,如果您只是使用componentsSeparatedByString("\n"),您可能會收到意想不到的結果。

let multiLineString = "Line 1\r\nLine 2\r\nLine 3\r\n" 
let lineArray = multiLineStringRN.componentsSeparatedByString("\n") 
// ["Line 1\r", "Line 2\r", "Line 3\r", ""] 

注意剩餘的\r和空數組元素。

有幾種方法可以避免這些問題。

1. componentsSeparatedByCharactersInSet

let multiLineString = "Line 1\nLine 2\r\nLine 3\n" 
let newlineChars = NSCharacterSet.newlineCharacterSet() 
let lineArray = multiLineString.componentsSeparatedByCharactersInSet(newlineChars).filter{!$0.isEmpty} 
// "[Line 1, Line 2, Line 3]" 

如果filter不使用,那麼會\r\n因爲它被計數爲兩個字符產生一個空數組元素等在分隔串兩次同一地點。

2. split

let multiLineString = "Line 1\nLine 2\r\nLine 3\n" 
let newlineChars = NSCharacterSet.newlineCharacterSet() 
let lineArray = multiLineString.utf16.split { newlineChars.characterIsMember($0) }.flatMap(String.init) 
// "[Line 1, Line 2, Line 3]" 

let multiLineString = "Line 1\nLine 2\r\nLine 3\n" 
let lineArray = multiLineString.characters.split { $0 == "\n" || $0 == "\r\n" }.map(String.init) 
// "[Line 1, Line 2, Line 3]" 

這裏\r\n被計數爲單一夫特字符(擴展字形簇)

3. enumerateLines

let multiLineString = "Line 1\nLine 2\r\nLine 3\n" 
var lineArray = [String]() 
multiLineString.enumerateLines { (line, stop) ->() in 
    lineArray.append(line) 
} 
// "[Line 1, Line 2, Line 3]" 

欲瞭解更多有關enumerateLine語法,請參閱this answer也。

注:

  • 多線串通常不會混合使用這兩個\r\n\n,但我在這裏做這表明,這些方法可以處理這兩種格式。
  • NSCharacterSet.newlineCharacterSet()是換行符,定義爲(U + 000A-U + 000D,U + 0085),其中包括\r\n
  • 本答案是對my previous question的答案的總結。閱讀這些答案以獲取更多細節。
4

斯威夫特3版本:

let lines = yourString.components(separatedBy: .newlines) 

尼斯和短。

0

這是我對此採取:

NSString* string = @"FOO\r\nBAR\r\r\n\rATZ\rELM327 v1.5"; 
    NSCharacterSet* newlineSet = [NSCharacterSet newlineCharacterSet]; 
    NSCharacterSet* whitespaceSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 
    NSArray<NSString*>* components = [string componentsSeparatedByCharactersInSet:newlineSet]; 
    NSPredicate* predicate = [NSPredicate predicateWithBlock:^BOOL(NSString* _Nullable string, NSDictionary<NSString *,id> * _Nullable bindings){ 
     return [string stringByTrimmingCharactersInSet:whitespaceSet].length > 0; 
    }]; 
    NSArray<NSString*>* lines = [components filteredArrayUsingPredicate:predicate]; 

    [lines enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 
     NSLog(@"Line %u = '%@'", idx, obj); 
    }]; 

運行此版畫:

2017-10-24 15:26:05.380 Untitled 5[64977:3182818] Line 0 = 'FOO' 
2017-10-24 15:26:05.380 Untitled 5[64977:3182818] Line 1 = 'BAR' 
2017-10-24 15:26:05.380 Untitled 5[64977:3182818] Line 2 = 'ATZ' 
2017-10-24 15:26:05.380 Untitled 5[64977:3182818] Line 3 = 'ELM327 v1.5' 

它可能不是最有效的方法(可能使用NSScanner會更快),但它解決了問題在這裏。