2009-11-18 2 views
17

J'utilise Scala 2.8.0 et en essayant de lire tube fichier délimité comme dans le code ci-dessous snipped:Comment faire pour résoudre java.nio.charset.UnmappableCharacterException dans Scala 2.8.0?

object Main { 
    def main(args: Array[String]) :Unit = { 
    if (args.length > 0) { 
     val lines = scala.io.Source.fromPath("QUICK!LRU-2009-11-15.psv") 
    for (line <-lines) 
     print(line) 
    } 
    } 
} 

est ici l'erreur:

Exception dans le thread "principal" java.nio.charset. UnmappableCharacterException: Longueur d'entrée = 1 à java.nio.charset.CoderResult.throwException (CoderResult.java:261) à sun.nio.cs.StreamDecoder.implRead (StreamDecoder.java:319) à sun.nio.cs. StreamDecoder.read (StreamDecoder.java:158) à java.io.InputStreamReader.read (InputStreamReader.java:167) à java.io.BufferedReader.fill (BufferedReader.java:136) à java.io.BufferedReader.read (BufferedReader.java:157) à scala.io.BufferedSource $$ anonfun $ 1 $$ anonfun $ s'appliquent $ 1. apply (BufferedSource.scala: 29) à scala.io.BufferedSource $$ anonfun $ 1 $$ anonfun $ appliquer $ 1.apply (BufferedSource.scala: 29) à scala.io.Codec.wrap (Codec.scala: 65) à scala.io.BufferedSource $$ anonfun $ 1.apply (BufferedSource.scala: 29) à scala.io.BufferedSource $$ anonfun $ 1.apply (BufferedSource.scala: 29) à scala.collection.Iterator $$ anon $ 14.next (Iterator.scala: 149) à scala.collection.Iterator $$ anon $ 2.next (Iterator.scala: 745) à scala.collection.Iterator $$ anon $ 2.head (Iterator.scala: 732) à scala.collection.Iterator $$ anon $ 24.hasNext (Iterator.scala: 405) à scala.collection.Iterator $$ anon $ 20.hasNext (Iterator.scala: 320) à scala.io.Source.hasNext (Source. scala: 209) à scala.collection.Iterator $ class.foreach (Iterator.scala: 534) à scala.io.Source.foreach (Source.scala: 143) ... à infillreports.Main $ .main (Main.scala: 8) à infillreports.Main.main (Main.scala) Java Résultat: 1

Répondre

24
object Main { 
    def main(args: Array[String]) :Unit = { 
    if (args.length > 0) { 
     val lines = scala.io.Source.fromPath("QUICK!LRU-2009-11-15.psv")("UTF-8") 
     for (line <-lines) 
     print(line) 
    } 
    } 
} 
+1

Vous êtes simplement génial !!!! Merci beaucoup. –

+0

J'espère que vous prendrez le temps de comprendre pourquoi l'ajout de "UTF-8" ici était nécessaire, et comment il a changé le comportement de la lecture des caractères du flux d'entrée. Si vous ne l'obtenez pas, veuillez élaborer votre question ici ou poser une nouvelle question concernant les octets, les caractères et les encodages de caractères. – seh

+1

Dans scala 2.12.3 vous devriez écrire Source.fromFile (fileName) (Codec ("utf-8")) –

7

je luttais avec cette même question et cette réponse m'a aidé. Je voulais prolonger le commentaire de SEH concernant le 'pourquoi ça marche'. La réponse devrait reposer sur la signature de la méthode:

def fromFile(file: JFile)(implicit codec: Codec): BufferedSource 

Il prend un paramètre de codec implicite. Pourtant, sur l'exemple, une chaîne est fournie, pas un codec. Une deuxième traduction se déroule dans les coulisses: L'objet compagnon de la classe Codec définit une méthode applicable à partir chaîne:

def apply(encoding: String): Codec 

de sorte que le compilateur a fait un travail pour nous: lignes val = Source.fromFile (somefile) (Codec (« UTF-8 »))

Étant donné que le codec est implicite, si vous appelez cette méthode plusieurs fois, vous pouvez également créer un objet Codec dans le cadre de l'appel:

implicit val codec = Codec("UTF-8") 
val lines = Source.fromFile(someFile) 
val moreLines = Source.fromFile(someOtherFile) 

J'espère que j'ai eu ce r ight (Je suis toujours un Scala n00b, je prends les choses en main - n'hésitez pas à corriger si nécessaire)

+1

En fait, puisque Codec.apply n'est pas une conversion implicite, il n'y a aucune raison pour que le compilateur soit silencieusement appeler. En fait, c'est 'Codec.string2codec' qui est appelé ici (car ** est ** une conversion implicite de' String' à 'Codec') –

4

Ajouter à Daniel C.La réponse de Sobral, vous pouvez aussi essayer quelque chose comme ceci:

val products = Source.fromFile("products.txt")("UTF-8").getLines().toList; 

for(p <- products){ 
     println("product :" + p); 
} 
0

Ce peut-être une solution plus générique:

implicit val codec = Codec("UTF-8") 
codec.onMalformedInput(CodingErrorAction.REPLACE) 
codec.onUnmappableCharacter(CodingErrorAction.REPLACE) 

avec les deux paramètres, vous pouvez éviter les données malformés dans le fichier.

+0

Salut, je voulais essayer votre solution parce que la réponse acceptée n'a pas résolu mon problème. Mais il ne compile pas, car le compilateur ne reconnaît pas la valeur CodingErrorAction.REPLACE. J'ai importé scala.io._, quel espace de noms manque-t-il? – rumtscho

+0

Il vous manque 'java.nio.charset.CodingErrorAction' –

Questions connexes