0

Swift で char ごとにファイルを読み取る必要があります。私がやっている方法は、FileHandler からチャンクを読み取り、文字列の最初の文字を返すことです。

これまでの私のコードは次のとおりです。

/// Return next character, or nil on EOF.
func nextChar() -> Character? {
    precondition(fileHandle != nil, "Attempt to read from closed file")

    if atEof {
        return nil
    }

    if self.stored.characters.count > 0 {
        let c: Character = self.stored.characters.first!
        stored.remove(at: self.stored.startIndex)
        return c
    }

    let tmpData = fileHandle.readData(ofLength: (4096))
    print("\n---- file read ---\n" , terminator: "")
    if tmpData.count == 0 {
        return nil
    }

    self.stored = NSString(data: tmpData, encoding: encoding.rawValue) as String!
    let c: Character = self.stored.characters.first!
    self.stored.remove(at: stored.startIndex)
    return c
}

これに関する私の問題は、キャラクターの復帰が非常に遅いことです。これは私のテスト実装です:

if let aStreamReader = StreamReader(path: file) {
    defer {
        aStreamReader.close()
    }
    while let char = aStreamReader.nextChar() {
        print("\(char)", terminator: "")
        continue
    }
}

プリントがなくても、ファイルを最後まで読むのに何年もかかりました。

1.4MB のサンプル ファイルの場合、タスクを完了するのに 6 分以上かかりました。

time ./.build/debug/read a.txt
real    6m22.218s
user    6m13.181s
sys     0m2.998s

この部分を高速化する方法について意見はありますか?

let c: Character = self.stored.characters.first!
stored.remove(at: self.stored.startIndex)
return c

どうもありがとう。ps

++++ 更新された機能 ++++

func nextChar() -> Character? {
    //precondition(fileHandle != nil, "Attempt to read from closed file")

    if atEof {
        return nil
    }

    if stored_cnt > (stored_idx + 1) {
        stored_idx += 1
        return stored[stored_idx]
    }

    let tmpData = fileHandle.readData(ofLength: (chunkSize))
    if tmpData.count == 0 {
        atEof = true
        return nil
    }

    if let s = NSString(data: tmpData, encoding: encoding.rawValue) as String! {
        stored = s.characters.map { $0 }
        stored_idx = 0
        stored_cnt = stored.count
    }
    return stored[0];
}
4

1 に答える 1

1

の実装nextCharは非常に非効率的です。

を作成してから何度Stringも呼び出しcharacters、その文字セットを何度も更新します。

を作成してStringから、その への参照のみを保存してみませんかcharacters。そして、インデックスを に追跡しますcharacters。何度も更新する代わりに、単純にインデックスをインクリメントして次の文字を返します。文字列を何度も更新する必要はありません。

最後の文字に到達したら、ファイルの次の部分を読み取ります。新しい文字列を作成し、文字とインデックスをリセットします。

于 2016-10-28T00:12:01.747 に答える