Jay Steingold
Jay Steingold

Reputation: 13

txt files with invisible line breaks

I have two identical files level1.txt and lvl2.txt. Both are UTF-8 and line spacing MacOS/Unix

ㅏ: ah
ㅓ: eo/uh
ㅡ: eu
ㅣ: i
ㅗ: o/oh

I am reading them in and placing them in card objects. However, the first file works and second detects an extra line break, which creates an empty array element and gives me a fatal error index out of range because there isn't a first and second element of an empty string.

I have tried recreating level2.txt by making a new file both in the xcode editor and in textEditor and copy/pasting the code from the working text file, but it still detects a line break that isn't there. Could someone explain why this is happening or a better way to create text files to be used in xcode projects that won't leave invisible formatting. Thank you.

    if let levelFilePath = Bundle.main.path(forResource: "level\(indexPath.row + 1)", ofType: "txt") {

            if let levelContents = try? String(contentsOfFile: levelFilePath) {
                print(levelContents)
                //Split Q and A's by linebreak
                let lines = levelContents.components(separatedBy: "\n")

                for line in lines{
                    //Splits each line into answer and clue
                    let parts = line.components(separatedBy: ":")

                    let card = Card(question: parts[0], answer: parts[1])
                    currentDeck.append(card)
                }

Upvotes: 0

Views: 705

Answers (2)

vadian
vadian

Reputation: 285069

First of all I recommend to separate the lines by CharacterSet.newlines which considers all usual newline characters.

Second of all just filter empty lines.

let lines = levelContents.components(separatedBy: CharacterSet.newlines)
                         .filter{ !$0.isEmpty }

PS: Be aware that separating each line by a single colon causes a leading space character on the right side according to your text sample.

Upvotes: 1

Jim Matthews
Jim Matthews

Reputation: 1191

One option is to have your code ignore lines with fewer or more than 2 components, e.g.:

for line in lines{
    //Splits each line into answer and clue
    let parts = line.components(separatedBy: ":")
    guard parts.count == 2 else { continue }

    let card = Card(question: parts[0], answer: parts[1])
    currentDeck.append(card)
}

Upvotes: 0

Related Questions