How to split a string with newlines

前端 未结 6 1522
天涯浪人
天涯浪人 2020-12-29 21:44

I read from a csv file, and want to split the long string that I get using stringWithContentsOfFile, which is a multi line string, with individual lines representing rows in

6条回答
  •  青春惊慌失措
    2020-12-29 22:16

    You should be aware that \n is not the only character used to split a new line. For example, if the file was saved in Windows, the newline characters would be \r\n. Read the Newline article in Wikipedia for more information about this.

    Thus, if you just use componentsSeparatedByString("\n"), you may get unexpected results.

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

    Note both the residual \r and the empty array element.

    There are several ways to avoid these problems.

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

    If filter were not used, then \r\n would produce an empty array element because it gets counted as two characters and so separates the string twice at the same location.

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

    or

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

    Here \r\n gets counted as a single Swift character (an extended grapheme cluster)

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

    For more about the enumerateLine syntax, see this answer also.

    Notes:

    • a multi line string would not usually mix both \r\n and \n but I am doing this here to show that these methods can handle both formats.
    • NSCharacterSet.newlineCharacterSet() are newline characters defined as (U+000A–U+000D, U+0085), which include \r and \n.
    • This answer is a summary of the answers to my previous question. Read those answers for more detail.

提交回复
热议问题