1.读取数据在Scala语言的Source单例对象中中,提供了一些非常便捷的方法,从而使开发者可以快速的从指定数据源(文本文件,URL地址等)中获取数据,在使用Source单例对
1. 读取数据
在Scala语言的 Source 单例对象中 中, 提供了一些非常便捷的方法, 从而使开发者可以快速的从指定数据源(文本文件, URL地址等)中获取数据, 在使用 Source 单例对象 之前, 需要先导包, 即 import scala.io.Source .
1.1 按行读取
我们可以以 行 为单位, 来读取数据源中的数据, 返回值是一个 迭代器类型的对象 . 然后通过 toArray, toList 方法, 将这些数据放到数组或者列表中即可.
注意: Source类扩展自Iterator[Char]
格式
val source:BufferedSource = Source.fromFile("数据源文件的路径","编码表")
val lines:Iterator[String] = source.getLines()
val list1:List[String] = lines.toList
source.close()
需求
- 在当前项目下创建data文件夹, 并在其中创建1.txt文本文件, 文件内容如下:
好好学习 , 天天向上!
Hadoop, Zookeeper, Flume, Spark
Flink, Sqoop, HBase
- 以行为单位读取该文本文件中的数据, 并打印结果.
参考代码
import scala.io.Source
object ClassDemo01 {def main(args: Array[String]): Unit &#61; {val source &#61; Source.fromFile("./data/1.txt")var lines: Iterator[String] &#61; source.getLines()val list1 &#61; lines.toListfor(s <- list1) println(s)source.close()}
}
1.2 按字符读取
Scala还提供了 以字符为单位读取数据 这种方式, 这种用法类似于迭代器, 读取数据之后, 我们可以通过 hasNext(),next()方法 , 灵活的获取数据.
格式
val source:BufferedSource &#61; Source.fromFile("数据源文件的路径","编码表")
val iter:BufferedIterator[Char] &#61; source.buffered
while(iter.hasNext) {print(iter.next())
}
source.close()
注意:
如果文件不是很大, 我们可以直接把它读取到一个字符串中.
val str:String &#61; source.mkString
需求
- 在当前项目下创建data文件夹, 并在其中创建1.txt文本文件, 文件内容如下:
好好学习 , 天天向上!
Hadoop, Zookeeper, Flume, Spark
Flink, Sqoop, HBase
- 以行为单位读取该文本文件中的数据, 并打印结果.
参考代码
import scala.io.Source
object ClassDemo02 {def main(args: Array[String]): Unit &#61; {val source &#61; Source.fromFile("./data/1.txt")val iter &#61; source.buffered while(iter.hasNext) {print(iter.next()) }val str &#61; source.mkStringprintln(str)source.close()}
}
1.3 读取词法单元和数字
所谓的词法单元指的是 以特定符号间隔开的字符串 , 如果数据源文件中的数据都是 数字形式的字符串 , 我们可以很方便的从文件中直接获取这些数据, 例如:
10 2 5
11 2
5 1 3 2
格式
val source:BufferedSource &#61; Source.fromFile("数据源文件的路径","编码表")
val arr:Array[String] &#61; source.mkString.split("\\s&#43;")
val num &#61; strNumber.map(_.toInt)
source.close()
需求
- 在当前项目下创建data文件夹, 并在其中创建2.txt文本文件, 文件内容如下:
10 2 5
11 2
5 1 3 2
- 读取文件中的所有整数, 将其加1后, 把结果打印到控制台.
参考代码
import scala.io.Source
object ClassDemo03 {def main(args: Array[String]): Unit &#61; {val source &#61; Source.fromFile("./data/2.txt")val strNumber &#61; source.mkString.split("\\s&#43;") val num &#61; strNumber.map(_.toInt)for(a <- num) println(a &#43; 1)}
}
1.4 从URL或者其他源读取数据
Scala中提供了一种方式, 可以让我们直接从指定的URL路径, 或者其他源(例如: 特定的字符串)中直接读取数据。
格式
val source &#61; Source.fromURL("http://www.erainm.com")
println(source.mkString)
val str &#61; Source.fromString("好好学习")
println(str.getLines())
需求
- 读取 网址 (http://www.erainm.com) 页面的数据, 并打印结果.
- 直接读取字符串 好好学习 , 并打印结果.
参考代码
import scala.io.Source
object ClassDemo04 {def main(args: Array[String]): Unit &#61; {val source &#61; Source.fromURL("http://www.erainm.com")println(source.mkString)val str &#61; Source.fromString("好好学习")println(str.getLines())}
}
1.5 读取二进制文件
Scala没有提供读取二进制文件的方法, 我们需要通过Java类库来实现.
需求
已知项目的data文件夹下有 01.png 这张图片, 请读取该图片数据, 并将读取到的字节数打印到控制台上.
参考代码
object ClassDemo05 {def main(args: Array[String]): Unit &#61; {val file &#61; new File("./data/01.png")val fis &#61; new FileInputStream(file)val bys &#61; new Array[Byte](file.length().toInt)fis.read(bys)fis.close()println(bys.length)}
}
2. 写入数据
Scala并没有内建的对写入文件的支持, 要写入数据到文件, 还是需要使用Java的类库.
2.1 往文件中写入指定数据
需求
往项目下的data文件夹的3.txt文本文件中, 编写一句话, 内容如下:
好好学习 ,
天天向上!
参考代码
object ClassDemo06 {def main(args: Array[String]): Unit &#61; {val pw &#61; new FileOutputStream("./data/3.txt")pw.write("好好学习,\r\n".getBytes())pw.write("天天向上!".getBytes())pw.close()}
}
2.2 序列化和反序列化
在Scala中, 如果想将对象传输到其他虚拟机, 或者临时存储, 就可以通过 序列化和反序列化 来实现了.
- 序列化 : 把对象写到文件中的过程.
- 反序列化 : 从文件中加载对象的过程.
注意: 一个类的对象要想实现序列化和反序列化操作, 则该类必须继承 Serializable 特质 .
需求:
- 定义样例类Person, 属性为姓名和年龄.
- 创建Person样例类的对象p.
- 通过序列化操作将对象p写入到项目下的data文件夹下的4.txt文本文件中.
- 通过反序列化操作从项目下的data文件夹下的4.txt文件中, 读取对象p.
参考代码
object ClassDemo07 {case class Person(var name:String, var age:Int)def main(args: Array[String]): Unit &#61; {val ois &#61; new ObjectInputStream(new FileInputStream("./data/4.txt"))var p: Person &#61; ois.readObject().asInstanceOf[Person]println(p)}
}
3. 案例: 学员成绩表
3.1 概述
- 已知项目下的data文件夹的student.txt文本文件中, 记录了一些学员的成绩, 如下:
格式为: 姓名 语文成绩 数学成绩 英语成绩
张三 37 90 100
李四 90 73 81
王五 60 90 76
赵六 89 21 72
田七 100 100 100
- 按照学员的总成绩降序排列后, 按照 姓名 语文成绩 数学成绩 英语成绩 总成绩 的格式, 将数据写到项目下的data文件夹的stu.txt文件中.
3.2 目的
考察 流 , 样例类, 以及函数式编程 相关内容.
3.3 步骤
- 定义样例类Person, 属性为: 姓名, 语文成绩, 数学成绩, 英语成绩, 且该类中有一个获取总成绩的方法.
- 读取指定文件(./data/student.txt)中所有的数据, 并将其封装到List列表中.
- 定义可变的列表ListBuffer[Student], 用来记录所有学生的信息.
- 遍历第二步获取到的数据, 将其封装成Person类的对象后, 并添加到ListBuffer中.
- 对第4步获取到的数据进行排序操作, 并将其转换成List列表.
- 按照指定格式, 通过BufferWriter将排序后的数据写入到目的地文件中(./data/stu.txt)
- 关闭流对象.
3.4 参考代码
object ClassDemo08 {case class Student(name:String, chinese:Int, math:Int, english:Int) {def getSum() &#61; chinese &#43; math &#43; english
}def main(args: Array[String]): Unit &#61; {val source &#61; Source.fromFile("./data/student.txt")var studentList: Iterator[List[String]] &#61; source.getLines().map(_.split("")).map(_.toList)val list &#61; new ListBuffer[Student]()for(s <- studentList) {list &#43;&#61; Student(s(0), s(1).toInt, s(2).toInt, s(3).toInt)}val sortList &#61; list.sortBy(_.getSum()).reverse.toListval bw &#61; 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")bw.close()}
}