web-dev-qa-db-fra.com

Quelle est la différence entre toString et mkString in scala?

J'ai un fichier qui contient 10 lignes - je veux le récupérer, puis les scinder avec un séparateur de nouvelle ligne ("\ n").

voici ce que j'ai fait

val data = io.Source.fromFile("file.txt").toString;

Mais cela provoque une erreur lorsque j'essaie de scinder le fichier sur les nouvelles lignes.

J'ai ensuite essayé

val data = io.Source.fromFile("file.txt").mkString;

Et ça a marché.

Que diable? Quelqu'un peut-il me dire quelle est la différence entre les deux méthodes?

22
alan

Regardons les types, allons-nous? 

scala> import scala.io._
import scala.io._

scala> val foo = Source.fromFile("foo.txt")
foo: scala.io.BufferedSource = non-empty iterator

scala> 

Maintenant, la variable dans laquelle vous avez lu le fichier foo.txt est un itérateur. Si vous effectuez l'invocation toString() dessus, il ne renvoie pas le contenu du fichier, mais la représentation sous forme de chaîne de l'itérateur que vous avez créé. OTOH, mkString() lit l'itérateur (c'est-à-dire itère dessus) et construit une chaîne longue en fonction des valeurs lues. 

Pour plus d'informations, regardez cette session de console:

scala> foo.toString
res4: Java.lang.String = non-empty iterator

scala> res4.foreach(print)
non-empty iterator
scala> foo.mkString
res6: String = 
"foo
bar
baz
quux
dooo
"

scala> 
33
S.R.I

La méthode toString est supposée renvoyer la représentation sous forme de chaîne d'un objet. Il est souvent supplanté de fournir une représentation significative. La méthode mkString est définie sur les collections et est une méthode qui associe les éléments de la collection à la chaîne fournie. Par exemple, essayez quelque chose comme:

val a = List("a", "b", "c")
println(a.mkString(" : "))

et vous obtiendrez "a: b: c" en sortie. La méthode mkString a créé une chaîne de votre collection en joignant les éléments de la collection à la chaîne fournie. Dans le cas particulier que vous avez posté, l'appel mkString a rejoint les éléments renvoyés par l'itérateur BufferedSource avec la chaîne vide (c'est parce que vous avez appelé mkString sans argument). Cela résulte en une simple concaténation de toutes les chaînes (fournies par l'itérateur BufferedSource) de la collection.

D'un autre côté, appeler toString ici n'a pas vraiment de sens, car ce que vous obtenez (quand vous ne recevez pas d'erreur) est la représentation sous forme de chaîne de l'itérateur BufferedSource; qui vous dit juste que l'itérateur n'est pas vide.

23
nomad

Ce sont différentes méthodes dans différentes classes. Dans ce cas, mkString est une méthode du trait GenTraversableOnce. toString est défini sur Any (et est très souvent remplacé).

Le moyen le plus simple (ou du moins celui que j'utilise habituellement) de le savoir est d'utiliser la documentation de http://www.scala-lang.org/api/current/index.html . Commencez par le type de votre variable:

val data = io.Source.fromFile("file.txt")

est de type

scala.io.BufferedSource

Accédez à la documentation de BufferedSource et recherchez mkString. Dans la doc de mkString (cliquez sur la flèche vers le bas à gauche), vous verrez que cela vient de 

Definition Classes TraversableOnce → GenTraversableOnce

Et faire la même chose avec toString.

1
James Moore

Je pense que le problème est de comprendre ce que fait la classe Source. D'après votre code, il semblerait que Source.fromFile récupère le contenu d'un fichier alors que son rôle est de pointer vers le début du fichier.

Ceci est typique lorsque vous travaillez avec des opérations d'E/S où vous devez ouvrir une "connexion" avec une ressource (dans ce cas, une connexion avec votre système de fichiers), lire/écrire plusieurs fois, puis fermer cette "connexion". Dans votre exemple, vous ouvrez une connexion à un fichier et vous devez lire ligne par ligne le contenu du fichier jusqu'à la fin. Pensez que lorsque vous lisez, vous chargez des informations en mémoire. Ce n'est donc pas une bonne idée de charger tout le fichier en mémoire dans la plupart des scénarios (ce que mkString va faire).

Dans l’autre main, mkString est utilisé pour parcourir tous les éléments d’une collection. Par conséquent, dans ce cas, il consiste à lire le fichier et à charger un Array [String] en mémoire. Soyez prudent, car si le fichier est volumineux, votre code va échouer. Normalement, lorsque vous utilisez des E/S, vous devez utiliser un tampon pour lire du contenu, puis traiter/enregistrer ce contenu, puis charger plus de contenu (dans le même tampon), en évitant les problèmes. avec mémoire. Par exemple, la lecture de 5 lignes -> analyse -> enregistrer les lignes analysées -> lire les 5 lignes suivantes -> etc.

Vous pouvez également comprendre que "toString" ne vous récupère rien ... vous indique simplement "vous pouvez lire des lignes, le fichier n'est pas vide".

0
Carlos Verdes