Scala与Mongodb实践2-----图片、日期的存储读取

目的:在IDEA中实现图片、日期等相关的类型在mongodb存储读取

  • 主要是Scala和mongodb里面的类型的转换。Scala里面的数据编码类型和mongodb里面的存储的数据类型各个不同。存在类型转换。
  • 而图片和日期的转换如下图所示。

 

 

 

 1、日期的存取

  • 简单借助java.until.Calendar即可。
1
2
3
val ca=Calendar.getInstance()
ca.set()
ca.getTime

 

  • 有多种具体的格式等,再直接应用mgoDateTime等方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//显示各种格式
type MGODate = java.util.Date
  def mgoDate(yyyy: Int, mm: Int, dd: Int): MGODate = {
    val ca = Calendar.getInstance()
    ca.set(yyyy,mm,dd)
    ca.getTime()
  }
  def mgoDateTime(yyyy: Int, mm: Int, dd: Int, hr: Int, min: Int, sec: Int): MGODate = {
    val ca = Calendar.getInstance()
    ca.set(yyyy,mm,dd,hr,min,sec)
    ca.getTime()
  }
  def mgoDateTimeNow: MGODate = {
    val ca = Calendar.getInstance()
    ca.getTime
  }
  def mgoDateToString(dt: MGODate, formatString: String): String = {
    val fmt= new SimpleDateFormat(formatString)
    fmt.format(dt)
  }

  

2、图片的存取(看图片大小,一般都是如下,大于16M的图片即采用GridFS,分别将图片的属性存储)

借助Akka的FileStream

将File(图片)===》Array[Byte]代码格式,图片在mongodb中显示形式binary

 

 

具体代码如下:

1
FileStreaming.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.company.files
 
import java.nio.file.Paths
import java.nio._
import java.io._
import akka.stream.{Materializer}
import akka.stream.scaladsl.{FileIO, StreamConverters}
 
import scala.concurrent.{Await}
import akka.util._
import scala.concurrent.duration._
 
object FileStreaming {
  def FileToByteBuffer(fileName: String, timeOut: FiniteDuration)(
    implicit mat: Materializer):ByteBuffer = {
    val fut = FileIO.fromPath(Paths.get(fileName)).runFold(ByteString()) { case (hd, bs) =>
      hd ++ bs
    }
    (Await.result(fut, timeOut)).toByteBuffer
  }
 
  def FileToByteArray(fileName: String, timeOut: FiniteDuration)(
    implicit mat: Materializer): Array[Byte] = {
    val fut = FileIO.fromPath(Paths.get(fileName)).runFold(ByteString()) { case (hd, bs) =>
      hd ++ bs
    }
    (Await.result(fut, timeOut)).toArray
  }
 
  def FileToInputStream(fileName: String, timeOut: FiniteDuration)(
    implicit mat: Materializer): InputStream = {
    val fut = FileIO.fromPath(Paths.get(fileName)).runFold(ByteString()) { case (hd, bs) =>
      hd ++ bs
    }
    val buf = (Await.result(fut, timeOut)).toArray
    new ByteArrayInputStream(buf)
  }
 
  def ByteBufferToFile(byteBuf: ByteBuffer, fileName: String)(
    implicit mat: Materializer) = {
    val ba = new Array[Byte](byteBuf.remaining())
    byteBuf.get(ba,0,ba.length)
    val baInput = new ByteArrayInputStream(ba)
    val source = StreamConverters.fromInputStream(() => baInput)  //ByteBufferInputStream(bytes))
    source.runWith(FileIO.toPath(Paths.get(fileName)))
  }
 
  def ByteArrayToFile(bytes: Array[Byte], fileName: String)(
    implicit mat: Materializer) = {
    val bb = ByteBuffer.wrap(bytes)
    val baInput = new ByteArrayInputStream(bytes)
    val source = StreamConverters.fromInputStream(() => baInput) //ByteBufferInputStream(bytes))
    source.runWith(FileIO.toPath(Paths.get(fileName)))
  }
 
  def InputStreamToFile(is: InputStream, fileName: String)(
    implicit mat: Materializer) = {
    val source = StreamConverters.fromInputStream(() => is)
    source.runWith(FileIO.toPath(Paths.get(fileName)))
  }
}
  • Helpers.scala  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.company.lib
 
import java.util.concurrent.TimeUnit
 
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import java.text.SimpleDateFormat
import java.util.Calendar
import org.mongodb.scala._
 
object Helpers {
 
  implicit class DocumentObservable[C](val observable: Observable[Document]) extends ImplicitObservable[Document] {
    override val converter: (Document) => String = (doc) => doc.toJson
  }
 
  implicit class GenericObservable[C](val observable: Observable[C]) extends ImplicitObservable[C] {
    override val converter: (C) => String = (doc) => doc.toString
  }
 
  trait ImplicitObservable[C] {
    val observable: Observable[C]
    val converter: (C) => String
 
    def results(): Seq[C] = Await.result(observable.toFuture(), Duration(10, TimeUnit.SECONDS))
    def headResult() = Await.result(observable.head(), Duration(10, TimeUnit.SECONDS))
    def printResults(initial: String = ""): Unit = {
      if (initial.length > 0) print(initial)
      results().foreach(res => println(converter(res)))
    }
    def printHeadResult(initial: String = ""): Unit = println(s"${initial}${converter(headResult())}")
  }
 
 
  type MGODate = java.util.Date
  def mgoDate(yyyy: Int, mm: Int, dd: Int): MGODate = {
    val ca = Calendar.getInstance()
    ca.set(yyyy,mm,dd)
    ca.getTime()
  }
  def mgoDateTime(yyyy: Int, mm: Int, dd: Int, hr: Int, min: Int, sec: Int): MGODate = {
    val ca = Calendar.getInstance()
    ca.set(yyyy,mm,dd,hr,min,sec)
    ca.getTime()
  }
  def mgoDateTimeNow: MGODate = {
    val ca = Calendar.getInstance()
    ca.getTime
  }
 
 
  def mgoDateToString(dt: MGODate, formatString: String): String = {
    val fmt= new SimpleDateFormat(formatString)
    fmt.format(dt)
  }
 
}

 

  •  Model.scala

模型中包含了两个具体的模型Person和Address,二者是包含关系,具体模型内含存取方法

 

 

                                        

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package com.company.demo
 
import org.mongodb.scala._
import bson._
import java.util.Calendar
import com.company.files._
 
import akka.stream.ActorMaterializer
 
object Models {
//Model可存在在不同的模型,下面存在一个拥有代表性的模型Person
 
  case class Address(
                    //Scala中的字段类型,且String的默认参数是“”
                    city: String ="",
                    zipcode: String = ""
                    ) {
    def toDocument: Document =
      bson.Document(      
 //bson.Document是bson包里面的Document,其他包内有不同的Document
        "city" -> city,
        "zipcode" -> zipcode
      )
    def fromDocument(doc: Document): Address =
      this.copy(
        city = doc.getString("city"),
        zipcode = doc.getString("zipcode")
      )
  }
    //这是日期的设置
  val ca = Calendar.getInstance()
  ca.set(2001,10,23)
  val defaultDate = ca.getTime
  case class Person (
                    lastName: String = "Doe",
                    firstName: String = "John",
                    age: Int = 1,
                    phones: List[String] = Nil,
                    address: List[Address] = Nil,
                    birthDate: java.util.Date = defaultDate,
                    picture: Array[Byte] = Array()
                    ) { ctx =>
    def toDocument: Document = {
      var doc = bson.Document(
        "lastName" -> ctx.lastName,
        "firstName" -> ctx.firstName,
        "age" -> ctx.age,
        "birthDate" -> ctx.birthDate
      )
      if (ctx.phones != Nil)
        doc = doc + ("phones" -> ctx.phones)
      if (ctx.address != Nil)
        doc = doc + ("address" -> ctx.address.map(addr => addr.toDocument))
      if (!ctx.picture.isEmpty)
        doc = doc + ("picture" -> ctx.picture)
 
      doc
 
    }
    import scala.collection.JavaConverters._
    def fromDocument(doc: Document): Person = {
        //keySet
      val ks = doc.keySet
      ctx.copy(
        lastName = doc.getString("lastName"),
        firstName = doc.getString("firstName"),
        age = doc.getInteger("age"),
        phones = {
            doc.get("phones").asInstanceOf[Option[BsonArray]] match {
            case Some(barr) => barr.getValues.asScala.toList.map(_.toString)
            case None => Nil
          }
        },
        address = {
          if (ks.contains("address")) {
            doc.get("address").asInstanceOf[Option[BsonArray]] match {
              case Some(barr) => barr.getValues.asScala.toList.map (
                ad => Address().fromDocument(ad.asDocument())
              )
              case None => Nil
            }
          }
          else Nil
        },
        picture = {
          if (ks.contains("picture")) {
            doc.get("picture").asInstanceOf[Option[BsonBinary]] match {
              case Some(ba) => ba.getData
              case None => Array()
            }
          }
          else Array()
        }
      )
    }
     //在控制台显示的格式。
    def toSink()(implicit mat: ActorMaterializer) = {
      println(s"LastName: ${ctx.lastName}")
      println(s"firstName: ${ctx.firstName}")
      println(s"age: ${ctx.age}")
      println(s"phones: ${ctx.phones}")
      println(s"address ${ctx.address}")
      if(!ctx.picture.isEmpty) {
        val path = s"/img/${ctx.firstName}.jpg"
        FileStreaming.ByteArrayToFile(ctx.picture,path)
        println(s"picture saved to: ${path}")
      }
    }
 
  }
 
 
}

  

  •  PersonCRUD.scala简单测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.company.demo
 
import org.mongodb.scala._
import bson._
import java.util.Calendar
import scala.collection.JavaConverters._
import com.company.lib.Helpers._
import com.company.files.FileStreaming._
import akka.actor._
import akka.stream._
import scala.concurrent.duration._
import scala.util._
 
object PersonCRUD extends  App {
  import Models._
 
    implicit val system = ActorSystem()
    implicit val ec = system.dispatcher
    implicit val mat = ActorMaterializer()
 
    // or provide custom MongoClientSettings
    val settings: MongoClientSettings = MongoClientSettings.builder()
      .applyToClusterSettings(b => b.hosts(List(new ServerAddress("localhost")).asJava))
      .build()
    val client: MongoClient = MongoClient(settings)
    val mydb = client.getDatabase("mydb")
    val mytable = mydb.getCollection("personal")
 
    val susan = Person(
      lastName = "Wang",
      firstName = "Susan",
      age = 18,
      phones = List("137110998","189343661"),
      address = List(
        Address("Sz","101992"),
        Address(city = "gz", zipcode="231445")
      ),
      birthDate = mgoDate(2001,5,8),
      picture = FileToByteArray("/img/sc.jpg",3 seconds)
    )
/*
    val futResult = mytable.insertOne(susan.toDocument).toFuture()
 
    futResult.onComplete {
      case Success(value) => println(s"OK! ${value}")
      case Failure(err) => println(s"Boom!!! ${err.getMessage}")
    }
 
    scala.io.StdIn.readLine() */<br>
  mytable.find().toFuture().andThen {
    case Success(ps) => ps.foreach(Person().fromDocument(_).toSink())
    case Failure(err) => println(s"ERROR: ${err.getMessage}")
  }
  scala.io.StdIn.readLine()
  system.terminate()
  }

  

posted @   ~~。  阅读(399)  评论(0编辑  收藏  举报
编辑推荐:
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 《HelloGitHub》第 106 期
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
点击右上角即可分享
微信分享提示