标签:
我们要构建这样一个应用,它会取回一份列表,其中包括用户持有的股票的代码以及股份,并告知他们在当前日期为止的这些投资的总价。这包含了几件事:获取用户输入、读文件、解析数据、写文件、从Web获取数据、把信息显示给用户。
我们会先开发一个控制台应用。然后,把它转换成Swing应用。一次一步,沿着这条路重构应用。
Scala的Console类可以从命令行获取用户输入。
下面的代码将信息读入内存:
package com.cn.gao //获取用户输入 class ConsoleInput { print("Please enter a tiker symbol:") val symbol = Console.readLine //val symbol = readLine //This will work too println("OK, got it, you own " + symbol) } //object ConsoleInput extends App{ // new ConsoleInput() //}
程序运行结果如下:
Please enter a tiker symbol:AAPL
OK, got it, you own AAPL
用java.io.File可以做这件事。下面是个写文件的例子:
package com.cn.gao import java.io._ //写文件 class WriteToFile { val writer = new PrintWriter(new File("D:\\symbols.txt")) writer write "AAPL" writer.close() } //object WriteToFile extends App{ // new WriteToFile() //}
上面的这段代码将股票代码"AAPL"写入到文件D:\\symbols.txt里。文件内容如下:
AAPL
读文件写真的很简单。Scala的Source类及其伴生对象就是为这种目的而存在的。为了演示,我们写了一个Scala脚本:
package com.cn.gao import scala.io.Source /** * 读文件 */ class ReadingFile { println("请输入你要读出的文件完整路径:") val name = readLine //或者Console.readLine Source.fromFile(name).foreach(print) } object ReadingFile extends App{ new ReadingFile() }
在上面的代码里,读取了相应的文件,打印出其内容如下所示:
请输入你要读出的文件完整路径: D://data.txt linux的特点 1.免费的/开源 2.支持多线程./多用户的 3.安全性好 4.对内存和文件管理优越. linux最小只需要4m->嵌入式开发 samba服务器用于和windows进行交互 从事网络开发必读三本书: TCP/ip详解,协议 实现 TCP事务协议 http nntp和UNIX域协议 tracert 目标ip/域名 查看经过的网关数目(追踪路由) ping 目标ip 测试两个ip是否畅通 1.在windows中查看ip情况的命令是ipconfig 2.在linux/unix下查看ip命令是ifconfig linux网络环境配置 第一种方法: (1)用root身份登录,运行setup命令进入到text mode setup utiliy对 网络进行配置。这里可以进行ip,子网掩码,默认网关,dns的设置。 (2)这时网卡配置没有生效,运行/etc/rc.d/init.d/network restart命 令我们刚才作的设置生效 第二种方法: (1)ifconfig eth0 x.x.x.x对网卡进行设置 (2)ifconfig eth0 network x.x.x.x对子网掩码设置 对广播地址和dns使用默认的。 注意:这样配置网络将会立即生效,但是是临时生效。 第三种方法: (1)修改/etc/sysconfig/network-scripts/ifconfig-eth0这个文件里各个 属性可以修改,包括ip,子网掩码,广播地址,默认网关。 (2)这时网卡的配置没有生效,运行/etc/rc.d/init.d/network restart 命令我们刚才作的设置才生效。 这种方法是最底层的修改方法 samba的安装步骤 a.看看是否已经安装了samba rpm -q samba b.如有,如何卸载 rpm -e samba rpm -e --nodeps samba http://blog.csdn.net/eric491179912/article/details/6179908
Source类是一个输入流上的Iterator。Source的伴生对象有几个便利方法去读文件、输入流、字符串甚至是URL,稍后会看到。foreach()方法一次读取一个字符(输入是缓冲的,不必担心性能)。如果需要一次读一行,那就用getLines()方法。
很快我们就会从Web读信息了。因此,讨论Source时,让我们看看它的fromURL()方法。这个方法可以读取网站、web服务或是任何可以用URL指向东西的内容。下面是个例子,读入Scala文档站点,确定文档相关的Scala版本号:
package com.cn.gao import scala.io.Source import java.net.URL /** * 从Web读取信息 */ class ReadingURL { val source = Source.fromURL( new URL("http://www.scala-lang.org/docu/files/api/index.html")) println(source.getLine(3)) val content = source.mkString val VersionRegEx = """[\D\S]+scaladoc\s+\(version\s+(.+)\)[\D\S]+""".r content match { case VersionRegEx(version) => println("Scala doc for version: " + version) } } object ReadingURL extends App{ new ReadingURL() }
上面的代码调用fromURL()获得Source实例,这样,就可以从URL读取内容,然后进行迭代。将3传入getLine()方法,读取第三行。使用这个方法必须小心谨慎。索引值从1开始,而不是0,所以,第一行实际上是用索引1引用的。
Scala把XML当作一等公民。因此,不必把XML文档嵌入字符串,直接放入代码即可,就像放一个int或Double值一样。看个例子:
package com.cn.gao import scala.xml._ class UseXML { val xmlFragment = <symbols> <symbol ticker="AAPL"><units>200</units></symbol> <symbol ticker="IBM"><units>215</units></symbol> </symbols> println(xmlFragment) println(xmlFragment.getClass()) } object UseXML extends App { new UseXML() }
这里创建了一个val,叫做xmlFragment,直接把一些XML样例内容赋给它。Scala解析了XML的内容,欣然创建了一个scala.xml.Elem的实例,输出如下:
<symbols>
<symbol ticker="AAPL"><units>200</units></symbol>
<symbol ticker="IBM"><units>215</units></symbol>
</symbols>
class scala.xml.Elem
Scala的scala.xml包提供了一些类,用以读取、解析、创建和存储XML文档。
你或许用过XPath,它提供了一种强大的查询XML文档的方式。Scala提供了一种类似XPath的查询能力,但略有差异。对于辅助解析和提取的方法,Scala不用斜线(/和//)查询,而用反斜线(\和\\)。这个差异是必需的,因为Scala遵循Java的传统,使用两个斜线表示注释。这样,我们看一下如何解析手头上的这个XML片段。
首先,要获取symbol这个元素。为了做到这一点,可以使用类似XPath的查询,如下:
package com.cn.gao import scala.xml._ class UseXML { val xmlFragment = <symbols> <symbol ticker="AAPL"><units>200</units></symbol> <symbol ticker="IBM"><units>215</units></symbol> </symbols> // println(xmlFragment) // println(xmlFragment.getClass()) var symbolNodes = xmlFragment \ "symbol" println(symbolNodes.mkString("\n")) println(symbolNodes.getClass()) } object UseXML extends App { new UseXML() }
上面的代码的输出如下:
<symbol ticker="AAPL"><units>200</units></symbol>
<symbol ticker="IBM"><units>215</units></symbol>
class scala.xml.NodeSeq$$anon$1
这里调用了XML元素的\()方法,让它找到所有symbol元素。它会返回一个scala.xml.NodeSeq的实例,表示XML节点的集合。
\()方法只会找出是目标元素(本例子里是symbols元素)直接后代的元素。如果想从目标元素出发,搜出层次结构里所有的元素,就要用\\()方法,如下所示。此外,用text()方法可以获取元素里的文本节点。
package com.cn.gao import scala.xml._ class UseXML { val xmlFragment = <symbols> <symbol ticker="AAPL"><units>200</units></symbol> <symbol ticker="IBM"><units>215</units></symbol> </symbols> // println(xmlFragment) // println(xmlFragment.getClass()) // var symbolNodes = xmlFragment \ "symbol" // println(symbolNodes.mkString("\n")) // println(symbolNodes.getClass()) var unitsNodes = xmlFragment \\ "units" println(unitsNodes.mkString("\n")) println(unitsNodes.getClass()) println(unitsNodes(0).text) } object UseXML extends App { new UseXML() }
上面的代码的输出如下:
<units>200</units>
<units>215</units>
class scala.xml.NodeSeq$$anon$1
200
在上面的例子里,使用了text()方法去获取文本节点。模式匹配也可以获取文本值以及其他内容。如果想浏览XML文档的结构,\()和\\()两个方法很有用。不过,如果想匹配XML文档任意位置的内容,模式匹配会显得更有用。
Scala也将模式匹配扩展到了XML片段的匹配上,如下所示:
package com.cn.gao import scala.xml._ class UseXML { val xmlFragment = <symbols> <symbol ticker="AAPL"><units>200</units></symbol> <symbol ticker="IBM"><units>215</units></symbol> </symbols> // println(xmlFragment) // println(xmlFragment.getClass()) // var symbolNodes = xmlFragment \ "symbol" // println(symbolNodes.mkString("\n")) // println(symbolNodes.getClass()) var unitsNodes = xmlFragment \\ "units" // println(unitsNodes.mkString("\n")) // println(unitsNodes.getClass()) // println(unitsNodes(0).text) unitsNodes(0) match { case <units>{numberOfUnits}</units> => println("Units: " + numberOfUnits) } } object UseXML extends App { new UseXML() }
上面代码的输出如下:
Units: 200
这里,取出第一个units元素,让Scala提取出文本值200。在case语句里,我们对感兴趣的片段进行匹配,用一个变量numberOfUnits,当做这个元素的文本内容的占位符。
这样就可以获取到一支股票的股份了。不过还是有两个问题。前一种方式只对内容刚好匹配case里表达式的情况起作用;也就是说,units元素只能包含一个内容项或是一个子元素。如果它包含的是子元素和文本内容的混合体,上面的匹配就会失败。而且这里想得到的是所有股票的股份,而不是第一个。运用_*,就可以让Scala抓出所有的内容(元素和文本),如下所示:
package com.cn.gao import scala.xml._ class UseXML { val xmlFragment = <symbols> <symbol ticker="AAPL"><units>200</units></symbol> <symbol ticker="IBM"><units>215</units></symbol> </symbols> // println(xmlFragment) // println(xmlFragment.getClass()) // var symbolNodes = xmlFragment \ "symbol" // println(symbolNodes.mkString("\n")) // println(symbolNodes.getClass()) var unitsNodes = xmlFragment \\ "units" // println(unitsNodes.mkString("\n")) // println(unitsNodes.getClass()) // println(unitsNodes(0).text) // unitsNodes(0) match { // case <units>{numberOfUnits}</units> => println("Units: " + numberOfUnits) // } println("Ticker\tUnits") xmlFragment match { case <symbols>{symbolNodes @ _*}</symbols> => for(symbolNode @ <symbol>{_*}</symbol> <- symbolNodes){ println("%-7s %s".format( symbolNode \ "@ticker", (symbolNode \ "units").text)) //用@前缀表示属性查询 } } } object UseXML extends App { new UseXML() }
上面代码的输出如下:
Ticker Units AAPL 200 IBM 215
只有将XML读入内存,才能够进行解析。下一步,我们来了解如何将XML文档加载到程序里,如何把内存里的文档存入文件。作为例子,我们会加载一个包含股票代码和股份的文件,对股份加1,然后将更新的内容存回到另一个XML文件里。我们先来处理加载文件的这一步。
这是要加载的样例文件stocks.xml:
<symbols> <symbol ticker="AAPL"><units>200</units></symbol> <symbol ticker="ADBE"><units>125</units></symbol> <symbol ticker="ALU"><units>150</units></symbol> <symbol ticker="AMD"><units>150</units></symbol> <symbol ticker="CSCO"><units>250</units></symbol> <symbol ticker="HPQ"><units>225</units></symbol> <symbol ticker="IBM"><units>215</units></symbol> <symbol ticker="INTC"><units>160</units></symbol> <symbol ticker="MSFT"><units>190</units></symbol> <symbol ticker="NSM"><units>200</units></symbol> <symbol ticker="ORCL"><units>200</units></symbol> <symbol ticker="SYMC"><units>230</units></symbol> <symbol ticker="TXN"><units>190</units></symbol> <symbol ticker="VRSN"><units>200</units></symbol> <symbol ticker="XRX"><units>240</units></symbol> </symbols>
scala.xml的XML单例对象的load()方法可以辅助加载文件,如下所示:
package com.cn.gao
import scala.xml._
class ReadWriteXML {
val stocksAndUnits = XML.load("D:\\stocks.xml")
println(stocksAndUnits.getClass())
println("Loaded file has " + (stocksAndUnits \\ "symbol").size +
" symbol elements")
}
object ReadWriteXML extends App {
new ReadWriteXML()
}
从下面的输出可以看出,load()返回的是一个scala.xml.Elem实例。此外还可以看到,加载的文件(stocks.xml)包含15个symbol元素。
class scala.xml.Elem
Loaded file has 15 symbol elements
我们已经知道如何解析这个文档的内容,下面将股票代码以及其对应的股份存到Map里。下面这段代码做的就是这件事:
package com.cn.gao import scala.collection.mutable._ import scala.xml._ class ReadWriteXML { val stocksAndUnits = XML.load("D:\\stocks.xml") // println(stocksAndUnits.getClass()) // println("Loaded file has " + (stocksAndUnits \\ "symbol").size + // " symbol elements") val stocksAndUnitsMap = (Map[String, Int]() /: (stocksAndUnits \ "symbol")) {(map, symbolNode) => val ticker = (symbolNode \ "@ticker").toString val units = (symbolNode \ "units").text.toInt map(ticker) = units //Creates and returns a new Map } println("Number of symbol elements found is " + stocksAndUnitsMap.size) } object ReadWriteXML extends App { new ReadWriteXML() }
最后一步,增加股份值,创建数据的XML表示,存入文件。
package com.cn.gao import scala.collection.mutable._ import scala.xml._ class ReadWriteXML { val stocksAndUnits = XML.load("D:\\stocks.xml") // println(stocksAndUnits.getClass()) // println("Loaded file has " + (stocksAndUnits \\ "symbol").size + // " symbol elements") val stocksAndUnitsMap = (Map[String, Int]() /: (stocksAndUnits \ "symbol")) {(map, symbolNode) => val ticker = (symbolNode \ "@ticker").toString val units = (symbolNode \ "units").text.toInt map(ticker) = units //Creates and returns a new Map } println("Number of symbol elements found is " + stocksAndUnitsMap.size) val updatedStocksAndUnitsXML = <symbols> { stocksAndUnitsMap.map{ updateUnitsAndCreateXML }} </symbols> def updateUnitsAndCreateXML(element : (String, Int))= { val (ticker, units) = element <symbol ticker={ticker}> <units>{units + 1}</units> </symbol> } XML save ("D:\\stocks2.xml", updatedStocksAndUnitsXML) println("The saved file contains " + (XML.load("D:\\stocks2.xml") \\ "symbol").size = " symbol elements") } object ReadWriteXML extends App { new ReadWriteXML() }
package com.cn.gao import scala.swing._ import event._ object SampleGUI extends SimpleSwingApplication { def top = new MainFrame { title = "A Sample Scala Swing GUI" val label = new Label {text = "------------"} val button = new Button { text = "Click me"} contents = new FlowPanel { contents += label contents += button } listenTo(button) reactions += { case ButtonClicked(button) => label.text = "You clicked!" } } }
标签:
原文地址:http://www.cnblogs.com/gaopeng527/p/4394669.html