web-dev-qa-db-fra.com

Comment diviser une chaîne avec les nouvelles lignes

J'ai lu dans un fichier csv et je souhaite scinder la longue chaîne que j'obtiens à l'aide de stringWithContentsOfFile, une chaîne de plusieurs lignes, avec des lignes individuelles représentant les lignes du fichier csv. Comment puis-je faire cela?

23
Sonu Jha

Vous pouvez diviser la chaîne en tableaux de chaîne, puis manipuler à votre guise.

NSArray *brokenByLines=[yourString componentsSeparatedByString:@"\n"]
28
Dipendra

Juste au cas où quelqu'un tomberait comme moi sur cette question. Cela fonctionnera avec tous les caractères de nouvelle ligne:

NSCharacterSet *separator = [NSCharacterSet newlineCharacterSet];
NSArray *rows = [yourString componentsSeparatedByCharactersInSet:separator];
41
Diana Farin

Sachez que \n n'est pas le seul caractère utilisé pour fractionner une nouvelle ligne. Par exemple, si le fichier a été enregistré sous Windows, les caractères de nouvelle ligne sont \r\n. Lisez l'article de Newline dans Wikipedia pour plus d'informations à ce sujet.

Ainsi, si vous utilisez simplement componentsSeparatedByString("\n"), vous risquez d'obtenir des résultats inattendus.

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

Notez à la fois le \r résiduel et l'élément de tableau vide. 

Il y a plusieurs façons d'éviter ces problèmes. 

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

Si filter n'était pas utilisé, alors \r\n produirait un élément de tableau vide car il serait compté pour deux caractères et séparerait ainsi la chaîne deux fois au même endroit.

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

ou 

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

Ici, \r\n est compté comme un seul caractère Swift (un cluster de graphèmes étendu) 

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

Pour plus d'informations sur la syntaxe enumerateLine, voir this answer also.

Remarques:

  • une chaîne de plusieurs lignes ne mélange généralement pas \r\n et \n, mais je le fais ici pour montrer que ces méthodes peuvent gérer les deux formats.
  • NSCharacterSet.newlineCharacterSet() sont des caractères de nouvelle ligne définis comme (U + 000A – U + 000D, U + 0085), qui comprennent \r et \n.
  • Cette réponse est un résumé des réponses à ma question précédente . Lisez ces réponses pour plus de détails.
15
Suragch

Swift 3 version:

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

Sympa et court.

7
Clifton Labrum

Vous devez séparer votre contenu avec "\ 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]);
2
βhargavḯ

Voici mon point de vue sur elle:

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

Exécuter ces impressions:

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'

Ce n'est peut-être pas le moyen le plus efficace (utiliser probablement une NSScanner serait plus rapide), mais cela résout le problème ici.

0
DrMickeyLauer