Putting/Getting 使用 F# 在 SQLite 中压缩数据
Putting/Getting compressed data in SQLite with F#
我正在尝试将我的一个现有项目(网络抓取工具)从 Python 移植到 F#,以学习 F#。该程序的一个组件 save 使用 LZMA 压缩大字符串(原始 HTML),并将其存储在 SQLite 中的临时键值 table 中。 HTML 字符串应始终为 unicode。
因为我是 F# 初学者并且这需要大量的 .NET 互操作,所以我很困惑如何完成它。
我想知道如何在 F# 中正确执行此操作,并使用 LZMA 而不是 GZip。
编辑
我很难找到与 LZMA2 兼容的 .NET 库,因为 LZMA-SDK 使用 LZMA1。这与我使用 LZMA2 压缩的现有数据不兼容。因此,在评论的帮助下,我继续使用 Gzip 实现了这一点。
这使用 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
我正在尝试将我的一个现有项目(网络抓取工具)从 Python 移植到 F#,以学习 F#。该程序的一个组件 save 使用 LZMA 压缩大字符串(原始 HTML),并将其存储在 SQLite 中的临时键值 table 中。 HTML 字符串应始终为 unicode。
因为我是 F# 初学者并且这需要大量的 .NET 互操作,所以我很困惑如何完成它。
我想知道如何在 F# 中正确执行此操作,并使用 LZMA 而不是 GZip。
编辑
我很难找到与 LZMA2 兼容的 .NET 库,因为 LZMA-SDK 使用 LZMA1。这与我使用 LZMA2 压缩的现有数据不兼容。因此,在评论的帮助下,我继续使用 Gzip 实现了这一点。
这使用 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