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?
Vous pouvez diviser la chaîne en tableaux de chaîne, puis manipuler à votre guise.
NSArray *brokenByLines=[yourString componentsSeparatedByString:@"\n"]
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];
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.
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.
\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
.Swift 3 version:
let lines = yourString.components(separatedBy: .newlines)
Sympa et court.
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]);
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.