2013-03-01 13 views
19

Ho letto da un file csv e voglio dividere la stringa lunga che ottengo usando stringWithContentsOfFile, che è una stringa multi linea, con singole righe che rappresentano le righe nel file csv. Come faccio a fare questo?come dividere una stringa con newline

+0

Perché caricare l'intero file in memoria? Questo non aiuterà la tua impronta di memoria ... – trojanfoe

+0

Forse è noto che il file non sarà così grande. È * solo * testo ... – uchuugaka

+0

sì ... il file è abbastanza piccolo ... ha solo 54 righe e 4 colonne! –

risposta

26

È possibile suddividere la stringa in matrici di stringa e quindi manipolare come si desidera.

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

Questo fa un sacco di ipotesi su ciò che sono i separatori di riga. – uchuugaka

+1

Se non si conoscono i separatori di riga: 'let lines = stringData.stringByReplacingOccurrencesOfString (" \ r \ n ", withString:" \ "n"). StringByReplacingOccurrencesOfString ("\ r", withString: "\ n") .componentsSeparatedByString ("\ n") ' – Zaphod

+0

Uno non deve sostituire @" \ r ", se la stringa è separata con newLineCharacterSet; –

2

È necessario separare il contenuto con "\ 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

Questo fa anche supposizioni sui separatori di riga. – uchuugaka

37

Nel caso in cui qualcuno si imbattesse in questa domanda come ho fatto io. Questo funziona con qualsiasi caratteri di nuova riga:

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

Anche funziona con file CSV ... dove "\ n" non lo sarà. – DogCoffee

+3

Questo può produrre stringhe vuote nell'array se i separatori di riga sono '\ r \ n' (due caratteri) come accade nei file formattati di Windows. – Suragch

13

si deve essere consapevoli che \n non è l'unico carattere utilizzato per dividere una nuova linea. Ad esempio, se il file è stato salvato in Windows, i caratteri di nuova riga saranno \r\n. Leggi the Newline article in Wikipedia per ulteriori informazioni a riguardo.

Pertanto, se si utilizza solo componentsSeparatedByString("\n"), è possibile ottenere risultati imprevisti.

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", ""] 

nota sia il residuo \r e l'elemento array vuoto.

Esistono diversi modi per evitare questi problemi.

Solutions

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]" 

Se filter non sono stati utilizzati, quindi \r\n produrrebbe un elemento array vuoto perché viene contato come due caratteri, così separa la stringa due volte al stessa posizione

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]" 

o

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]" 

Qui \r\n ottiene contato come un singolo carattere Swift (un cluster grafema esteso)

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]" 

Per ulteriori informazioni sulla sintassi enumerateLine, vedere anche this answer.

Note:

  • una spezzata a più non sarebbe solito mescolare sia \r\n e \n ma sto facendo questo qui per dimostrare che questi metodi in grado di gestire entrambi i formati.
  • NSCharacterSet.newlineCharacterSet() sono caratteri di nuova riga definiti come (U + 000A-U + 000D, U + 0085), che includono \r e \n.
  • Questa risposta è un riepilogo delle risposte a my previous question. Leggi quelle risposte per maggiori dettagli.
4

Swift 3 versione:

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

Nizza e breve.

0

Ecco il mio prendere su di esso:

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); 
    }]; 

Esecuzione Questo stampa:

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' 

Esso non può essere il modo più efficiente (probabilmente utilizzando un NSScanner sarebbe più veloce), ma risolve il problema qui.