溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Scala文件操作方法有哪些

發(fā)布時間:2023-05-09 15:06:17 來源:億速云 閱讀:112 作者:zzz 欄目:開發(fā)技術(shù)

本篇內(nèi)容介紹了“Scala文件操作方法有哪些”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

    1. 讀取數(shù)據(jù)

    在Scala語言的  Source單例對象 中, 提供了一些非常便捷的方法, 從而使開發(fā)者可以快速的從指定數(shù)據(jù)源(文本文件, URL地址等)中獲取數(shù)據(jù), 在使用 Source單例對象 之前, 需要先導(dǎo)包, 即 import scala.io.Source.

    1.1 按行讀取

    我們可以以 行 為單位, 來讀取數(shù)據(jù)源中的數(shù)據(jù), 返回值是一個 迭代器類型的對象 . 然后通過 toArray, toList 方法, 將這些數(shù)據(jù)放到數(shù)組或者列表中即可.

    注意: Source類擴展自Iterator[Char]

    格式

    //1. 獲取數(shù)據(jù)源文件對象.
    val source:BufferedSource = Source.fromFile("數(shù)據(jù)源文件的路徑","編碼表")
    //2. 以行為單位讀取數(shù)據(jù).
    val lines:Iterator[String] = source.getLines()
    //3. 將讀取到的數(shù)據(jù)封裝到列表中.
    val list1:List[String] = lines.toList
    //4. 千萬別忘記關(guān)閉Source對象.
    source.close()

    需求

    在當(dāng)前項目下創(chuàng)建data文件夾, 并在其中創(chuàng)建1.txt文本文件, 文件內(nèi)容如下:

    好好學(xué)習(xí), 天天向上!
    Hadoop, Zookeeper, Flume, Spark
    Flink, Sqoop, HBase

    以行為單位讀取該文本文件中的數(shù)據(jù), 并打印結(jié)果.

    參考代碼

    import scala.io.Source
    object ClassDemo01 {
    	def main(args: Array[String]): Unit = {
    		//1. 獲取數(shù)據(jù)源對象.
    		val source = Source.fromFile("./data/1.txt")
    		//2.通過getLines()方法, 逐行獲取文件中的數(shù)據(jù).
    		var lines: Iterator[String] = source.getLines()
    		//3. 將獲取到的每一條數(shù)據(jù)都封裝到列表中.
    		val list1 = lines.toList
    		//4. 打印結(jié)果
    		for(s <- list1) println(s)
    		//5. 記得關(guān)閉source對象.
    		source.close()
    	}
    }

    1.2 按字符讀取

    Scala還提供了 以字符為單位讀取數(shù)據(jù) 這種方式, 這種用法類似于迭代器, 讀取數(shù)據(jù)之后, 我們可以通過 hasNext(),next()方法 , 靈活的獲取數(shù)據(jù).

    Scala使用source.buffered方法按字符讀取文件

    什么是source.buffered方法

    source.buffered方法是scala.io.Source類的一個成員方法,它可以將一個Source對象轉(zhuǎn)換為一個BufferedSource對象。BufferedSource對象是一個實現(xiàn)了BufferedIterator特質(zhì)的對象,它可以提供一個緩沖區(qū),用來存儲未被消費的元素。這樣可以提高讀取文件的效率,也可以方便地查看下一個元素而不消費它。

    如何使用source.buffered方法

    要使用source.buffered方法,首先需要導(dǎo)入scala.io.Source類,并創(chuàng)建一個Source對象,然后調(diào)用其buffered方法,得到一個BufferedSource對象。例如,以下代碼創(chuàng)建了一個從文件中獲取的Source對象,并轉(zhuǎn)換為一個BufferedSource對象:

    import scala.io.Source
    // 創(chuàng)建一個從文件中獲取的Source對象
    val source = Source.fromFile("demo.txt")
    // 調(diào)用buffered方法,得到一個BufferedSource對象
    val buffered = source.buffered

    然后,可以使用BufferedSource對象的各種方法來按字符讀取文件。例如,以下代碼使用head方法來查看下一個字符,使用next方法來消費下一個字符,并打印出來:

    // 使用head方法查看下一個字符
    println(buffered.head)
    // 使用next方法消費下一個字符
    println(buffered.next())
    // 繼續(xù)使用head方法查看下一個字符
    println(buffered.head)
    // 繼續(xù)使用next方法消費下一個字符
    println(buffered.next())

    最后,需要關(guān)閉Source對象,釋放資源:

    // 關(guān)閉Source對象source.close()
    一個示例

    下面給出一個完整的示例,演示如何使用source.buffered方法來按字符讀取文件,并打印出來。

    首先,準(zhǔn)備一個文本文件demo.txt,內(nèi)容如下:

    Hello, Scala!
    你好,Scala!

    然后,編寫以下代碼:

    import scala.io.Source
    // 創(chuàng)建一個從文件中獲取的Source對象,并轉(zhuǎn)換為一個BufferedSource對象
    val buffered = Source.fromFile("demo.txt").buffered
    // 循環(huán)判斷是否有下一個元素
    while (buffered.hasNext) {
      // 打印出當(dāng)前元素,并消費掉
      print(buffered.next())
    }
    // 關(guān)閉Source對象
    buffered.close()

    最后,運行程序,可以看到輸出結(jié)果如下:

    Hello, Scala!
    你好,Scala!

    1.3 讀取詞法單元和數(shù)字

    所謂的詞法單元指的是 以特定符號間隔開的字符串 , 如果數(shù)據(jù)源文件中的數(shù)據(jù)都是 數(shù)字形式的字符串 , 我們可以很方便的從文件中直接獲取這些數(shù)據(jù), 例如:

    10 2 5

    11 2

    5 1 3 2

    格式

    //1. 獲取數(shù)據(jù)源文件對象.
    val source:BufferedSource = Source.fromFile("數(shù)據(jù)源文件的路徑","編碼表")
    //2. 讀取詞法單元.
    // \s表示空白字符(空格, \t, \r, \n等)
    val arr:Array[String] = source.mkString.split("\\s+")
    //3. 將字符串轉(zhuǎn)成對應(yīng)的整數(shù)
    val num = strNumber.map(_.toInt)
    //4. 千萬別忘記關(guān)閉Source對象.
    source.close()

    參考代碼

    將上面的數(shù)字存入2.txt

    import scala.io.Source
    object ClassDemo03 {
    	def main(args: Array[String]): Unit = {
    	val source = Source.fromFile("./data/2.txt")
    	// \s表示空白字符(空格, \t, \r, \n等)
    	val strNumber = source.mkString.split("\\s+")
    	//將字符串轉(zhuǎn)成對應(yīng)的整數(shù)
    	val num = strNumber.map(_.toInt)
    	for(a <- num) println(a + 1)
    	}
    }

    1.4 從URL或者其他源讀取數(shù)據(jù)

    Scala中提供了一種方式, 可以讓我們直接從指定的URL路徑, 或者其他源(例如: 特定的字符串)中直接讀取數(shù)據(jù)。

    格式 從URL地址中讀取數(shù)據(jù)

    //1. 獲取數(shù)據(jù)源文件對象.
    val source = Source.fromURL("https://www.csdn.net")
    //2. 將數(shù)據(jù)封裝到字符串中并打印.
    println(source.mkString)

    從其他源讀取數(shù)據(jù)

    //1. 獲取數(shù)據(jù)源文件對象.
    val str = Source.fromString("CSDN")
    println(str.getLines())

    需求

    • 讀取https://www.csdn.net 頁面的數(shù)據(jù), 并打印結(jié)果.

    • 直接讀取字符串 CSDN, 并打印結(jié)果.

    參考代碼

    import scala.io.Source
    object ClassDemo04 {
    	def main(args: Array[String]): Unit = {
    	val source = Source.fromURL("https://www.csdn.net")
    	println(source.mkString)
    	val str = Source.fromString("CSDN")
    	println(str.getLines())
    	}
    }

    1.5 讀取二進制文件

    Scala沒有提供讀取二進制文件的方法, 我們需要通過Java類庫來實現(xiàn).

    需求 已知項目的data文件夾下有 05.png 這張圖片, 請讀取該圖片數(shù)據(jù), 并將讀取到的字節(jié)數(shù)打印到控制臺上. 參考代碼

    object ClassDemo05 {
    	def main(args: Array[String]): Unit = {
    	val file = new File("./data/04.png")
    	val fis = new FileInputStream(file)
    	val bys = new Array[Byte](file.length().toInt)
    	fis.read(bys)
    	fis.close()
    	println(bys.length)
    	}
    }

    2. 寫入文件

    2.1 使用java.io.PrintWriter類

    java.io.PrintWriter類是Java提供的一個用于寫入文本文件的類。它可以接受一個文件、一個輸出流或一個字符串作為參數(shù),然后通過調(diào)用其write方法來向文件中寫入數(shù)據(jù)。例如,以下代碼可以向文件hello.txt中寫入一行文本:

    import java.io._
    val pw = new PrintWriter(new File("hello.txt"))
    pw.write("Hello, world")
    pw.close()

    使用PrintWriter類寫入文件時,有兩個需要注意的問題:

    • PrintWriter類不會拋出異常,而是設(shè)置一個布爾標(biāo)志來表示是否發(fā)生了錯誤??梢酝ㄟ^調(diào)用其checkError方法來檢查是否有錯誤發(fā)生。

    • PrintWriter類默認(rèn)使用平臺的字符編碼,這可能導(dǎo)致不同平臺之間的不一致??梢酝ㄟ^指定字符編碼來避免這個問題。例如,以下代碼使用了UTF-8編碼:

    val pw = new PrintWriter(new File("hello.txt"), "UTF-8")

    2.2 使用java.io.FileWriter類

    java.io.FileWriter類是Java提供的另一個用于寫入文本文件的類。它是OutputStreamWriter的子類,可以接受一個文件或一個字符串作為參數(shù),然后通過調(diào)用其write方法來向文件中寫入數(shù)據(jù)。例如,以下代碼可以向文件test.txt中寫入一行文本:

    import java.io._
    val file = new File("test.txt")
    val bw = new BufferedWriter(new FileWriter(file))
    bw.write("We are learning Scala programming language")
    bw.close()

    使用FileWriter類寫入文件時,有兩個需要注意的問題:

    • FileWriter類會拋出IOExceptions異常,所以需要使用try-catch-finally語句來處理異常和關(guān)閉文件。

    • FileWriter類默認(rèn)使用平臺的字符編碼,這可能導(dǎo)致不同平臺之間的不一致。FileWriter類沒有提供指定字符編碼的構(gòu)造器,所以如果需要指定字符編碼,可以使用OutputStreamWriter類代替。例如,以下代碼使用了UTF-8編碼:

    val file = new File("test.txt")
    val bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"))
    bw.write("We are learning Scala programming language")
    bw.close()

    2.3 使用java.io.FileOutputStream類

    FileOutputStream是Java提供的一個用于寫入二進制文件的類,它是OutputStream的子類,可以接受一個文件或一個字符串作為參數(shù),然后通過調(diào)用其write方法來向文件中寫入字節(jié)數(shù)據(jù)。例如,以下代碼可以向文件data.bin中寫入一個整數(shù):

    import java.io._
    val file = new File("data.bin")
    val fos = new FileOutputStream(file)
    fos.write(42)
    fos.close()

    FileOutputStream類會拋出IOExceptions異常,所以需要使用try-catch-finally語句來處理異常和關(guān)閉文件。

    已收到消息. FileOutputStream是Java提供的一個用于寫入二進制文件的類,它是OutputStream的子類,可以接受一個文件或一個字符串作為參數(shù),然后通過調(diào)用其write方法來向文件中寫入字節(jié)數(shù)據(jù)。例如,以下代碼可以向文件data.bin中寫入一個整數(shù): scala import java.io._ val file = new File("data.bin") val fos = new FileOutputStream(file) fos.write(42) fos.close() FileOutputStream類會拋出IOExceptions異常,所以需要使用try-catch-finally語句來處理異常和關(guān)閉文件。

    2.4 幾種寫入的區(qū)別

    因為FileOutputStream類有兩種構(gòu)造器,一種接受一個文件對象作為參數(shù),一種接受一個字符串作為參數(shù)。如果接受一個字符串作為參數(shù),那么它會自動創(chuàng)建一個文件對象。所以,以下兩種寫法是等價的:

    val pw = new FileOutputStream(new File("./data/3.txt"))
    val pw = new FileOutputStream("./data/3.txt")

    但是,如果使用PrintWriter類或FileWriter類,那么就必須使用一個文件對象作為參數(shù),不能使用一個字符串。所以,以下兩種寫法是不等價的:

    val pw = new PrintWriter(new File("./data/3.txt"))
    val pw = new PrintWriter("./data/3.txt") // 錯誤

    2.5 使用第三方庫

    除了Java提供的類之外,還有一些第三方庫可以用來寫入文件,例如Apache Commons IO1和os-lib2等。這些庫通常提供了更簡潔和高效的API,也支持更多的功能和格式。例如,以下代碼使用了Apache Commons IO庫的FileUtils類來寫入文件,并指定了字符編碼:

    import org.apache.commons.io.FileUtils
    FileUtils.writeStringToFile(new File("test.txt"), "Hello, world", "UTF-8")

    以下代碼使用了os-lib庫的os.File對象來寫入文件,并返回一個字節(jié)長度:

    import os._
    os.write(os.pwd / "test.txt", "Hello, world")

    3. Scala序列化和反序列化

    3.1 什么是序列化和反序列化

    在Scala中,如果想將對象傳輸?shù)狡渌摂M機,或者臨時存儲,就可以通過序列化和反序列化來實現(xiàn)了。

    • 序列化:把對象寫到文件中的過程。

    • 反序列化:從文件中加載對象的過程。

    3.2 如何實現(xiàn)序列化和反序列化

    一個類的對象要想實現(xiàn)序列化和反序列化操作,則該類必須繼承Serializable特質(zhì)。Serializable特質(zhì)是一個空特質(zhì),它沒有任何方法和字段,只是用來標(biāo)記一個類是否可以被序列化和反序列化。

    要實現(xiàn)序列化操作,可以使用java.io.ObjectOutputStream類,它是一個用于寫入對象的輸出流。它可以接受一個輸出流作為參數(shù),然后通過調(diào)用其writeObject方法來寫入對象。

    要實現(xiàn)反序列化操作,可以使用java.io.ObjectInputStream類,它是一個用于讀取對象的輸入流。它可以接受一個輸入流作為參數(shù),然后通過調(diào)用其readObject方法來讀取對象。

    3.3 一個示例

    下面給出一個簡單的示例,演示如何使用case class和object來實現(xiàn)序列化和反序列化操作。

    首先,定義一個case class Person,屬性為姓名和年齡。注意,case class會自動繼承Serializable特質(zhì),所以不需要顯式地寫出來。

    // 定義一個case class Person
    case class Person(var name: String, var age: Int)

    然后,創(chuàng)建Person樣例類的對象p,并通過序列化操作將對象p寫入到項目下的data文件夾下的4.txt文本文件中。

    // 創(chuàng)建Person樣例類的對象p
    val p = Person("張三", 23)
    // 創(chuàng)建一個ObjectOutputStream對象,傳入一個輸出流作為參數(shù)
    val oos = new ObjectOutputStream(new FileOutputStream("./data/4.txt"))
    // 調(diào)用writeObject方法,將對象p寫入到輸出流中
    oos.writeObject(p)
    // 關(guān)閉輸出流
    oos.close()

    最后,通過反序列化操作從項目下的data文件夾下的4.txt文件中,讀取對象p,并打印出來。

    // 創(chuàng)建一個ObjectInputStream對象,傳入一個輸入流作為參數(shù)
    val ois = new ObjectInputStream(new FileInputStream("./data/4.txt"))
    // 調(diào)用readObject方法,從輸入流中讀取對象,并轉(zhuǎn)換為Person類型
    var p: Person = ois.readObject().asInstanceOf[Person]
    // 打印對象p
    println(p)
    // 關(guān)閉輸入流
    ois.close()

    3.4 使用注解

    除了使用Serializable特質(zhì)之外,還可以使用@SerialVersionUID注解來指定一個版本號。這樣可以避免不同版本的類之間的兼容性問題。例如,以下代碼定義了一個普通的類,并添加了注解:

    import java.io._
    // 使用@SerialVersionUID注解指定版本號為100L
    @SerialVersionUID(100L)
    // 定義一個普通的類,并繼承Serializable特質(zhì)
    class Person(var name: String, var age: Int) extends Serializable

    然后,可以使用相同的方式進行序列化和反序列化操作:

    val p = new Person("張三", 23)
    val oos = new ObjectOutputStream(new FileOutputStream("./data/4.txt"))
    oos.writeObject(p)
    oos.close()
    val ois = new ObjectInputStream(new FileInputStream("./data/4.txt"))
    var p: Person = ois.readObject().asInstanceOf[Person]
    println(p)

    案例-學(xué)員成績表

    概述

    已知項目下的data文件夾的student.txt文本文件中, 記錄了一些學(xué)員的成績, 如下: 格式為: 姓名 語文成績 數(shù)學(xué)成績 英語成績

    張三 37 90 100
    李四 90 73 81
    王五 60 90 76
    趙六 89 21 72
    田七 100 100 100

    按照學(xué)員的總成績降序排列后, 按照 姓名 語文成績 數(shù)學(xué)成績 英語成績 總成績 的格式, 將數(shù)據(jù)寫到項目下的data文件夾的stu.txt文件中.

    ** 步驟**

    • 定義樣例類Person, 屬性為: 姓名, 語文成績, 數(shù)學(xué)成績, 英語成績, 且該類中有一個獲取總成績的方法.

    • 讀取指定文件(./data/student.txt)中所有的數(shù)據(jù), 并將其封裝到List列表中.

    • 定義可變的列表ListBuffer[Student], 用來記錄所有學(xué)生的信息.

    • 遍歷第二步獲取到的數(shù)據(jù), 將其封裝成Person類的對象后, 并添加到ListBuffer中.

    • 對第4步獲取到的數(shù)據(jù)進行排序操作, 并將其轉(zhuǎn)換成List列表.

    • 按照指定格式, 通過BufferWriter將排序后的數(shù)據(jù)寫入到目的地文件中(./data/stu.txt)

    • 關(guān)閉流對象.

    參考代碼

    object ClassDemo08 {
    	//1. 定義樣例類Person, 屬性: 姓名, 語文成績, 數(shù)學(xué)成績, 英語成績, 且該類中有一個獲取總成績的方法.
    	case class Student(name:String, chinese:Int, math:Int, english:Int) 	{
    	def getSum() = chinese + math + english
    	}
    	def main(args: Array[String]): Unit = {
    	//2. 獲取數(shù)據(jù)源文件對象.
    	val source = Source.fromFile("./data/student.txt")
    	//3. 讀取指定文件(./data/student.txt)中所有的數(shù)據(jù), 并將其封裝到List列表中.
    	var studentList: Iterator[List[String]] = 	source.getLines().map(_.split(" ")).map(_.toList)
    	//4. 定義可變的列表ListBuffer[Student], 用來記錄所有學(xué)生的信息.
    	val list = new ListBuffer[Student]()
    	//5. 遍歷第二步獲取到的數(shù)據(jù), 將其封裝成Person類的對象后, 并添加到ListBuffer中.
    	for(s <- studentList) {list += Student(s(0), s(1).toInt, s(2).toInt, s(3).toInt)}
    	//6. 對第5步獲取到的數(shù)據(jù)進行排序操作, 并將其轉(zhuǎn)換成List列表.
    	val sortList = list.sortBy(_.getSum()).reverse.toList
    	//7. 按照指定格式, 通過BufferWriter將排序后的數(shù)據(jù)寫入到目的地文件(./data/stu.txt)
    	val bw = new BufferedWriter(new FileWriter("./data/stu.txt"))
    	for(s <- sortList) bw.write(s"${s.name} ${s.chinese} ${s.math} 	${s.english}${s.getSum()}\r\n")
    	//8. 關(guān)閉流對象
    	bw.close()
    	}
    }

    “Scala文件操作方法有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI