2013-02-27 16 views
7

Sto provando a leggere un file delle proprietà da classpath usando scala. Ma sembra che non funzionerà, è diverso da java. Il seguente frammento di codice 2, uno è java (funzionante), un altro è scala (non funziona). Non capisco qual è la differenza.Leggi il file delle proprietà in classpath usando scala

// working 
BufferedReader reader = new BufferedReader(new InputStreamReader(
Test.class.getResourceAsStream("conf/fp.properties"))); 

// not working 
val reader = new BufferedReader(new InputStreamReader(
getClass.getResourceAsStream("conf/fp.properties"))); 

Exception in thread "main" java.lang.NullPointerException 
at java.io.Reader.<init>(Reader.java:78) 
at java.io.InputStreamReader.<init>(InputStreamReader.java:72) 
at com.ebay.searchscience.searchmetrics.fp.conf.FPConf$.main(FPConf.scala:31) 
at com.ebay.searchscience.searchmetrics.fp.conf.FPConf.main(FPConf.scala) 
+0

Perché non usi [Config] (https://github.com/typesafehub/config)? –

+3

Ottenuto la soluzione, dovrei usare il percorso assoluto qui "/conf/fp.properties", ma non ancora chiaro sul perché il percorso relativo funziona in java ma non in scala – zjffdu

risposta

6

sto indovinando che il vostro BufferedReader è un java.io.BufferedReader

In questo caso si può semplicemente effettuare le seguenti operazioni:

import scala.io.Source.fromUrl 
val reader = fromURL(getClass.getResource("conf/fp.properties")).bufferedReader() 

Tuttavia, questo lascia la questione aperta su ciò che si sta progettando in seguito con lo reader. scala.io.Source ha già alcuni metodi utili che potrebbero rendere un sacco di vostro codice superfluo .. see ScalaDoc

+0

Cosa succede se il file di proprietà risiede nel file jar (es. In dir risorse)? –

+0

[Da] (http://stackoverflow.com/questions/5285898/how-to-get-a-resource-within-scalatest-w-sbt): 'val source = Source.fromURL (getClass.getResource ("/conf/fp.properties "))' – suls

+0

questo è il modo migliore approccio –

2

per la lettura di un file Properties mi consiglia di utilizzare java.util.ResourceBundle.getBundle("conf/fp"), rende la vita un po 'più facile.

0

L'eccezione NullPointerException che viene visualizzata è causata da un bug nel codice Java sottostante. potrebbe essere causato da un nome file errato.

A volte si ottiene questo errore anche se si sta tentando di caricare la risorsa con il classloader sbagliato.

  1. Controllare attentamente l'URL della risorsa rispetto al percorso di classe.
  2. Prova Source.fromInputStream(getClass.getResourceAsStream(...))
  3. Prova Source.fromInputStream(getClass.getClassLoader.getResourceAsStream())
  4. Forse state utilizzando altri classloader si può provare?

La stessa storia vale per Source.fromUrl(...)

Se stai cercando di caricare i file di configurazione e controllare il loro formato, si dovrebbe avere uno sguardo al programma di utilità di Typesafe Config.

0

L'eccezione Null Pointer che si ottiene è da getResourceAsStream che restituisce null. Il seguente frammento di junit.scala mostra come ci sia una differenza in class vs classloader. vedi What is the difference between Class.getResource() and ClassLoader.getResource()?. Qui presumo fileName è il nome di un file che risiede nel percorso classe, ma non un file accanto alla classe che esegue il test.

assertTrue(getClass.getClassLoader().getResourceAsStream(fileName) != null) 
assertTrue(getClass.getClassLoader().getResourceAsStream("/" + fileName) == null) 
assertTrue(getClass.getResourceAsStream(fileName) == null) 
assertTrue(getClass.getResourceAsStream("/" + fileName) != null) 
5

Questo codice finalmente funzionato per me:

import java.util.Properties 
import scala.io.Source 

// ... somewhere inside module. 

var properties : Properties = null 

val url = getClass.getResource("/my.properties") 
if (url != null) { 
    val source = Source.fromURL(url) 

    properties = new Properties() 
    properties.load(source.bufferedReader()) 
} 

e ora avete vecchi java.util.Properties semplici per gestire ciò che il mio codice legacy in realtà aveva bisogno di ricevere.

0

La mia soluzione preferita è con com.typesafe.scala-logging. Ho messo un file application.conf nella cartella principale \ risorse, con contenuti come:

services { mongo-db { retrieve = """http://xxxxxxxxxxxx""", base = """http://xxxxxx""" } }

e di usarlo in una classe, primo carico la fabbrica config da typesafe e poi basta usarlo.

val conf = com.typesafe.config.ConfigFactory.load() conf.getString("services.mongo-db.base"))

Speranza che aiuta!

Ps. Scommetto che ogni file sulle risorse con .conf come estensione verrà letto.

Problemi correlati