2016-10-28 4 views
0

Je dois lire un fichier char par char dans swift. La façon dont je le fais est de lire un morceau à partir d'un FileHandler et de retourner le premier caractère d'une chaîne.La lecture d'un char string par char est très lente dans ma mise en œuvre rapide

Ceci est mon code à ce jour:

/// 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 
} 

Mon problème est que le retour d'un personnage est très lent. Ceci est ma mise en œuvre de test:

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

même sans l'imprimer a pris des siècles pour lire le fichier à la fin.

pour un exemple de fichier avec 1.4mb il a fallu plus de six minutes pour terminer la tâche.

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

Avez-vous une opinion sur la façon d'accélérer cette pièce?

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

Merci beaucoup. ps

++++ UPDATEED FONCTION ++++

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]; 
} 
+0

Utilisez des instruments et voyez où tout le temps est passé. – rmaddy

+0

Dans les trois lignes j'ai posté au bas de mon message –

Répondre

1

Votre mise en œuvre de nextChar est terriblement inefficace.

Vous créez un String et puis appelez characters encore et encore et vous mettez à jour cet ensemble de caractères encore et encore. Pourquoi ne pas créer le String, puis ne stocker qu'une référence à characters. Et puis suivre un index dans characters. Au lieu de le mettre à jour encore et encore, il suffit d'incrémenter l'index et de retourner le caractère suivant. Pas besoin de mettre à jour la chaîne encore et encore.

Une fois que vous arrivez au dernier caractère, lisez le morceau suivant du fichier. Créez une nouvelle chaîne, réinitialisez les caractères et l'index.

+0

Merci beaucoup! –

+0

J'ai maintenant un '' 'var stocké: [Character] = Array()' '' et retourne '' 'let r = stored [stored_idx]; stored_idx + = 1; return r} '' 'le 1.4 est rapide, mais le fichier 150mb prend encore 2,33 min. Y a-t-il même une meilleure mise en œuvre? –

+0

voici ma classe actuelle: https://gist.github.com/petershaw/51db7df73e4bf06bb935a3abb41d8b64 –