1. 凈資產應用實例
我們要構建這樣一個應用,它會取回一份列表,其中包括用戶持有的股票的代碼以及股份,並告知他們在當前日期為止的這些投資的總價。這包含了幾件事:獲取用戶輸入、讀文件、解析數據、寫文件、從Web獲取數據、把信息顯示給用戶。
我們會先開發一個控制台應用。然后,把它轉換成Swing應用。一次一步,沿着這條路重構應用。
2. 獲取用戶輸入
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
3. 讀寫文件
用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引用的。
4. XML,作為一等公民
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
5. 讀寫XML
只有將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() }
6. GUI使用示例
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!" } } }