Подтвердить что ты не робот

Как разбить строку на новые строки

Я прочитал из файла csv и хочу разделить длинную строку, которую я получаю, используя stringWithContentsOfFile, которая представляет собой многострочную строку, с отдельными строками, представляющими строки в файле csv. Как это сделать?

4b9b3361

Ответ 1

Вы можете разбить строку на массивы строки и затем манипулировать, как хотите.

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

Ответ 2

На всякий случай кто-то наткнется на этот вопрос, как я. Это будет работать с любыми символами новой строки:

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

Ответ 3

Вы должны знать, что \n не является единственным символом, используемым для разделения новой строки. Например, если файл был сохранен в Windows, символы новой строки будут \r\n. Подробнее читайте статью Newline в Википедии.

Таким образом, если вы просто используете 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 подсчитывается как один символ Swift (расширенный кластер графем)

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 см. этот ответ.

Примечания:

  • многострочная строка обычно не смешивает как \r\n, так и \n, но я делаю это здесь, чтобы показать, что эти методы могут обрабатывать оба формата.
  • NSCharacterSet.newlineCharacterSet() - символы новой строки, определенные как (U + 000A-U + 000D, U + 0085), которые включают \r и \n.
  • Этот ответ представляет собой резюме ответов на мой предыдущий вопрос. Прочтите эти ответы для более подробной информации.

Ответ 4

версия Swift 3:

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

Приятный и короткий.

Ответ 5

Вам нужно разделить свой контент на "\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]);

Ответ 6

Вот мой пример:

    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 будет быстрее), но он решает проблему здесь.