2012-12-18 12 views
8

मैं स्कैला में लिखे गए एक छोटे जीयूआई आवेदन पर काम कर रहा हूं। कुछ सेटिंग्स हैं जो उपयोगकर्ता जीयूआई में सेट करेंगे और मैं चाहता हूं कि वे प्रोग्राम निष्पादन के बीच बने रहें। असल में मैं एक scala.collections.mutable.Map चाहता हूं जो संशोधित होने पर स्वचालित रूप से एक फ़ाइल में बनी रहती है।मैं स्कैला एप्लिकेशन के लिए बुनियादी कॉन्फ़िगरेशन कैसे प्रदान करूं?

ऐसा लगता है कि यह एक आम समस्या होनी चाहिए, लेकिन मैं हल्के समाधान खोजने में असमर्थ हूं। यह समस्या आम तौर पर हल कैसे होती है?

+0

मैं JSON4s का उपयोग कर जेएसओएन को क्रमबद्ध करने के लिए समाप्त हुआ https://github.com/json4s/json4s सभी सुझावों के लिए धन्यवाद। – Dave

उत्तर

9

मैं इसमें बहुत कुछ करता हूं, और मैं .properties फ़ाइलों का उपयोग करता हूं (यह जावा-भूमि में बेवकूफ है)। हालांकि, मैं डिज़ाइन द्वारा अपनी कॉन्फ़िगरेशन को सीधे सीधा-आगे रखता हूं। यदि आपके पास नेस्टेड कॉन्फ़िगरेशन संरचनाएं हैं तो आप वाईएएमएल (यदि इंसान मुख्य लेखक हैं) या JSON या XML (यदि मशीन लेखक हैं) जैसे एक अलग प्रारूप चाहते हैं।

import java.io._ 
import java.util._ 
import scala.collection.JavaConverters._ 

val f = new File("test.properties") 
// test.properties: 
// foo=bar 
// baz=123 

val props = new Properties 

// Note: in real code make sure all these streams are 
// closed carefully in try/finally 
val fis = new InputStreamReader(new FileInputStream(f), "UTF-8") 
props.load(fis) 
fis.close() 

println(props) // {baz=123, foo=bar} 

val map = props.asScala // Get to Scala Map via JavaConverters 
map("foo") = "42" 
map("quux") = "newvalue" 

println(map) // Map(baz -> 123, quux -> newvalue, foo -> 42) 
println(props) // {baz=123, quux=newvalue, foo=42} 

val fos = new OutputStreamWriter(new FileOutputStream(f), "UTF-8") 
props.store(fos, "") 
fos.close() 
+0

क्या एस्काला नेस्टेड प्रकारों के लिए काम करता है?मान लीजिए कि मैं एक JSON ऑब्जेक्ट की तरह कुछ लोड कर रहा हूं - शायद मैं एक नक्शा वापस लेना चाहूंगा जहां इसके कुछ मूल्य अन्य मानचित्र या सूचियां हों, और अन्य मानचित्र, सूचियां, संख्याएं, तार आदि शामिल हैं ... – user48956

0

मैं मानचित्र को गुणों और इसके विपरीत रूपांतरित करने का सुझाव देता हूं। "* .properties" फ़ाइलें जावा दुनिया में कॉन्फ़िगरेशन संग्रहीत करने के लिए मानक हैं, क्यों इसे स्कैला के लिए उपयोग नहीं करें?

0

आम तरीका * हैं। गुण, * .xml, चूंकि स्कैला xml को मूल रूप से समर्थन करता है, इसलिए जावा में xml कॉन्फ़िगरेशन का उपयोग करना आसान होगा।

1

यहाँ एक config पढ़ने के लिए एक्सएमएल और एक मामले वर्ग का उपयोग करने का एक उदाहरण है:

यहाँ लोड हो रहा है रंगमंच की सामग्री के लिए कुछ उदाहरण कोड के रूप में स्काला नक्शा जोड़ तोड़, उसके बाद फिर से .properties के रूप में बचत है,। एक वास्तविक वर्ग एक मानचित्र से बेहतर हो सकता है। (आप यह भी कर सकते हैं कि एसबीटी और कम से कम एक प्रोजेक्ट क्या करता है, कॉन्फ़िगर को स्केल स्रोत के रूप में ले जाएं और इसे संकलित करें; इसे सहेजना कम स्वचालित है या एक प्रतिलिपि स्क्रिप्ट के रूप में। मैंने गुग नहीं किया है, लेकिन किसी ने ऐसा किया होगा।

case class PluginDescription(name: String, classname: String) { 
    def toXML: Node = { 
    <plugin> 
     <name>{name}</name> 
     <classname>{classname}</classname> 
    </plugin> 
    } 
} 
object PluginDescription { 

    def fromXML(xml: Node): PluginDescription = { 
    // extract one field 
    def getField(field: String): Option[String] = { 
     val text = (xml \\ field).text.trim 
     if (text == "") None else Some(text) 
    } 
    def extracted = { 
     val name = "name" 
     val claas = "classname" 
     val vs = Map(name -> getField(name), claas -> getField(claas)) 
     if (vs.values exists (_.isEmpty)) fail() 
     else PluginDescription(name = vs(name).get, classname = vs(claas).get) 
    } 
    def fail() = throw new RuntimeException("Bad plugin descriptor.") 
    // check the top-level tag 
    xml match { 
     case <plugin>{_*}</plugin> => extracted 
     case _      => fail() 
    } 
    } 
} 

इस कोड को संजीदगी से एक मामले वर्ग के लागू कॉल:)

Here's the simpler code.

इस संस्करण में एक मामला वर्ग का उपयोग करता है। उपयोग का मामला यह है कि कॉन्फ़िगरेशन से अनुपलब्ध फ़ील्ड डिफ़ॉल्ट तर्कों द्वारा आपूर्ति की जा सकती हैं। यहां कोई प्रकार का रूपांतरण नहीं है। उदा।, case class Config(foo: String = "bar")

// isn't it easier to write a quick loop to reflect the field names? 
import scala.reflect.runtime.{currentMirror => cm, universe => ru} 
import ru._ 

def fromXML(xml: Node): Option[PluginDescription] = { 
    def extract[A]()(implicit tt: TypeTag[A]): Option[A] = { 
    // extract one field 
    def getField(field: String): Option[String] = { 
     val text = (xml \\ field).text.trim 
     if (text == "") None else Some(text) 
    } 

    val apply = ru.newTermName("apply") 
    val module = ru.typeOf[A].typeSymbol.companionSymbol.asModule 
    val ts = module.moduleClass.typeSignature 
    val m = (ts member apply).asMethod 
    val im = cm reflect (cm reflectModule module).instance 
    val mm = im reflectMethod m 

    def getDefault(i: Int): Option[Any] = { 
     val n = ru.newTermName("apply$default$" + (i+1)) 
     val m = ts member n 
     if (m == NoSymbol) None 
     else Some((im reflectMethod m.asMethod)()) 
    } 
    def extractArgs(pss: List[List[Symbol]]): List[Option[Any]] = 
     pss.flatten.zipWithIndex map (p => getField(p._1.name.encoded) orElse getDefault(p._2)) 
    val args = extractArgs(m.paramss) 
    if (args exists (!_.isDefined)) None 
    else Some(mm(args.flatten: _*).asInstanceOf[A]) 
    } 
    // check the top-level tag 
    xml match { 
    case <plugin>{_*}</plugin> => extract[PluginDescription]() 
    case _      => None 
    } 
} 

एक्सएमएल loadFile और save है, यह बहुत बुरा वहाँ Properties के लिए कोई एक लाइनर हो रहा है है।

$ scala 
Welcome to Scala version 2.10.0-RC5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_06). 
Type in expressions to have them evaluated. 
Type :help for more information. 

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

scala> import java.util._ 
import java.util._ 

scala> import java.io.{StringReader, File=>JFile} 
import java.io.{StringReader, File=>JFile} 

scala> import scala.collection.JavaConverters._ 
import scala.collection.JavaConverters._ 

scala> val p = new Properties 
p: java.util.Properties = {} 

scala> p load new StringReader(
    | (new File(new JFile("t.properties"))).slurp) 

scala> p.asScala 
res2: scala.collection.mutable.Map[String,String] = Map(foo -> bar) 
1

यह सब एक फाइल करने के लिए एक नक्शा/वस्तु serializing करने पर निर्भर करता है, अपने विकल्प हैं: एक्सएमएल को

  • क्रमबद्धता बाईटकोड को

    • क्लासिक क्रमबद्धता
    • JSON को क्रमबद्धता (आसान जैक्सन, या लिफ्ट-जेएसओएन का उपयोग करके)
    • गुण फ़ाइल का उपयोग (बदसूरत, कोई utf-8 समर्थन)
    • एक प्रोपर के लिए क्रमबद्धता ietary प्रारूप (बदसूरत, पहिया reinvent)
  • संबंधित मुद्दे