使用F#在SQLite中放入/获取压缩数据

时间:2017-03-04 05:54:52

标签: f# system.data.sqlite

我正在尝试将我现有的项目(网络刮板)从Python移植到F#,以便学习F#。程序的一个组件使用LZMA保存压缩大字符串(原始HTML),并将其存储在临时键值表中的SQLite中。 HTML字符串应始终为unicode。

因为我是一名F#初学者,这需要大量的.NET互操作,所以我对如何实现这一点非常困惑。

我想知道如何在F#中正确地执行此操作,并使用LZMA而不是GZip。

修改

我很难找到兼容LZMA2的.NET库,因为LZMA-SDK使用LZMA1。这与使用LZMA2压缩的现有数据不兼容。因此,在评论的帮助下,我继续使用Gzip实现了这一点。

1 个答案:

答案 0 :(得分:1)

这使用Gzip进行压缩,并与Python 3.5中的gzip.compress / gzip.decompress函数兼容。

#if INTERACTIVE
#r "../packages/System.Data.SQLite.Core/lib/net46/System.Data.SQLite.dll"
#endif


open System.IO
open System.IO.Compression
open System.Data.SQLite

let compressString (s:string) =
  let bs = System.Text.Encoding.UTF8.GetBytes(s)
  use outStream = new MemoryStream()
  use gzOutStream = new GZipStream(outStream, CompressionMode.Compress, false)
  gzOutStream.Write(bs, 0, bs.Length)
  outStream.ToArray()

let decompressString (bs:byte[]) =
  use newInStream = new MemoryStream(bs)
  use gzOutStream = new GZipStream(newInStream, CompressionMode.Decompress, false)
  use sr = new StreamReader(gzOutStream)
  sr.ReadToEnd()

let insert dbc (key:string) (value:string) =
    let compressed = compressString value
    let cmd = new SQLiteCommand("INSERT into kvt (key, value) VALUES (@key, @value)", dbc)
    cmd.Parameters.Add(new SQLiteParameter("@key", key)) |> ignore
    cmd.Parameters.Add(new SQLiteParameter("@value", compressed)) |> ignore
    let res = cmd.ExecuteNonQuery()
    res

let fetch dbc (key:string) =
    let cmd = new SQLiteCommand("SELECT value FROM kvt WHERE key = @key", dbc)
    cmd.Parameters.Add(new SQLiteParameter("@key", key)) |> ignore
    let reader = cmd.ExecuteReader()
    reader.Read() |> ignore
    let compressed = unbox<byte[]> reader.["value"]
    decompressString compressed

let create() = 
    System.Data.SQLite.SQLiteConnection.CreateFile("mydb.sqlite")
    let dbc = new SQLiteConnection("Data Source=mydb.sqlite;Version=3;")
    dbc.Open()
    let cmd = new SQLiteCommand("CREATE TABLE kvt (key TEXT PRIMARY KEY, value BLOB)", dbc)
    let res = cmd.ExecuteNonQuery()
    dbc