最近利用空闲时间自己在写一个文件备份工具,因为我磁盘上的很多文件很重要,例如很多PPT和讲义。所以需要经常备份,而且因为这些文件很多,所以需要增量备份。
我尝试用过windows自带的ntbackup工具,但感觉不是很爽。它不支持压缩备份,而且界面也有点复杂。
为了响应伟大领袖的“自力更生,丰衣足食”的号召,咱决定自己写一个工具,专门备份到数据库。支持压缩,支持加密,支持增量。
本文分享一下其中一些重点的技术细节
其中一个关键的技术就是将文件使用二进制的方式存放在数据库的varbinary(max)的字段中。该字段最大允许的长度为2GB。
对于一些小文件,我们可以一次性读取它的所有字节,然后一次提交到数据库
/// <summary>
/// 这个方法演示了如何一次提交所有的字节。这样导致的结果是:应用程序立即需要申请等同于文件大小的内存
/// </summary>
static void SubmitFileByOnce() {
string file = @"F:\功夫熊猫rmvb";//文件大小为519MB
byte[] buffer = FileReadAllBytes(file);
using (SqlConnection conn = new SqlConnection("server=(local);database=demo;integrated security=true")) {
using (SqlCommand cmd = connCreateCommand())
{
cmdCommandText = "INSERT INTO Files(FileName,FileContents) VALUES(@fileName,@fileContents)";
cmdParametersAddRange(
new[]
{
new SqlParameter("@fileName",file),
new SqlParameter("@fileContents",buffer)
});
connOpen();
cmdExecuteNonQuery();
connClose();
}
}
}
但是,上面的方法有几个问题,主要体现在如果文件比较大的话
1 它需要一次性很大的内存,具体数据等同于文件大小。因为FileReadAllBytes方法是将所有字节全部读入到内存。
2 它会导致提交失败,就是因为数据太大了。数据库也会拒绝。
那么,我就对这个方法做了一下改进,将文件拆分为5MB一段,也就是说,此时每次申请的内存只有5MB。这就大大地提高了可用性。
/// <summary>
/// 这个方法是将文件切分为5MB的块,每次只是提交5MB,所以可能多次提交,但内存占用就比较小
/// </summary>
static void SubmitFileStepByStep() {
string file = @"F:\功夫熊猫rmvb";//以这个文件为例,大小为519MB,一共需要的时间大约94秒。还是有点慢的,所以还可能需要进行压缩
FileStream fs = new FileStream(file, FileModeOpen);
byte[] buffer = new byte[5 1024 1024];
int readCount;
using (SqlConnection conn = new SqlConnection("server=(local);database=demo;integrated security=true"))
{
connOpen();
while ((readCount = fsRead(buffer, 0, bufferLength)) > 0)
{
using (SqlCommand cmd = connCreateCommand())
{
cmdCommandText = "INSERT INTO Files(FileName,FileContents) VALUES(@fileName,@fileContents)";
cmdParametersAddRange(
new[]
{
new SqlParameter("@fileName",file),
new SqlParameter("@fileContents",buffer)
});
cmdExecuteNonQuery();
}
}
connClose();
}
}
这样的话,有一个后果就是一个文件,可能在数据库中会有多条记录。所以在读取的时候,我们需要对其进行合并
static void DownloadFile() {
string file = @"F:\功夫熊猫rmvb";
string destfile = @"E:\Temp\Tempwmv";
using (SqlConnection conn = new SqlConnection("server=(local);database=demo;integrated security=true"))
{
using (SqlCommand cmd = connCreateCommand())
{
cmdCommandText = "SELECT FileContents FROM Files WHERE FileName=@fileName";
cmdParametersAddRange(
new[]
{
new SqlParameter("@fileName",file),
});
connOpen();
SqlDataReader reader = cmdExecuteReader();
FileStream fs = new FileStream(destfile, FileModeAppend, FileAccessWrite);
while (readerRead())
{
byte[] buffer = (byte[])reader[0];
fsWrite(buffer, 0, bufferLength);
}
fsClose();
readerClose();
connClose();
}
}
}
本文由作者:陈希章
1、数据库是由主要文件、次要文件、事务日志文件所组成的。数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,数据管理不再仅仅是存储和管理数据。
2、在信息化社会,充分有效地管理和利用各类信息资源,是进行科学研究和决策管理的前提条件。数据库技术是管理信息系统、办公自动化系统、决策支持系统等各类信息系统的核心部分,是进行科学研究和决策管理的重要技术手段。
附加数据库
或者导入数据库
sql本身有数据导入的 *** 作。但如果要从一个备份的文件中导入数据,则要进行另外的 *** 作。下面以一个例子进行说明。
sql服务器上已有一个doe数据库,并且里面有大量的数据,现准备从另外一个备份文件a1bak(不是doe数据库的备份文件)中导入另外的数据(即导入后在doe中增加一些数据表,表中已录有数据),并保持原doe的数据不变。
1、首先,在“sql企业管理器”中新建一个临时数据库a1。
2、右击a1数据库,选择:所有任务->还原数据库。
3、在“还原数据库”窗口中,选择:“从设备”。
4、点击“选择设备”。
5、点击“添加”。
6、从文件名中选择要还原的数据库文件,如a1bak。
7、点击“确定”,返回“还原数据库”窗口。
8、点击“选项”卡,进入选项设置。
9、钩选:“在现有数据库上强制还原”。
10、修改“移到物理文件名”为:“c:\a1ldf”、“c:\a1mdf”。
11、点确定,即可导入备份文件中的数据到临时数据库a1中。
12、此时,你可以将数据从a1导入到另外一真正要导入的数据库中,如doe数据库。
(下面的数据导入 *** 作为sql2000企业管理器的一般数据导入导出 *** 作。)
13、在“sql企业管理器”中选择“doe”数据库。
14、右击doe数据库,选择:所有任务->导入数据。
15、在“dts导入/导出向导”窗口的“选择数据源”中,数据源选择刚才建立并导入数据的临时数据库a1。点击下一步。
16、在“选择目的”中,系统已经默认为doe数据库。
17、连续点击“下一步”,直到完成。
经过上面的 *** 作,你已经成功地将备份文件a1bak中数据导入doe数据库中,并且doe数据库原有数据不变。
此时,你可以删除临时数据库a1。
以上就是关于如何将大文件写入到数据库中全部的内容,包括:如何将大文件写入到数据库中、请问数据库是由什么文件组成的、mysql怎么导入和导出数据库文件等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)