我爱builder

C++Builder 程序员博客

比如我的服务器IP是固定的是:202.103.96.112
放在才:C:/qq.mdb
用户名:admin
密码:123456
大家可以告诉我下吗?请把那些组件都告诉我吧,我是新手。

Borland 的 MIDAS 技术
使用远程数据模块对你的 MDF 进行连接,客户端通过连接远程数据模块来访问数据库

也就是你的程序分为两部分,一个是服务端,服务端的本地有 MDF 文件,服务端连接上本地的 MDF 后,客户端通过网络访问你的服务端获取数据。

C/C++ code
// 怎么搞了2贴 ?

access不支持此种方式,建议用DCOM解决之。

网络卡,我开始点了还以为没点好,继续点了就2贴了。

进来看看。。这个应该是叫做访问数据库文件吧

无法连接

"\\202.103.96.112\Share$\qq.mdb"
唯一可做的只有共享目录方式,可以给共享目录一个受限的用户名/密码,
可以让它才能有读写权限;程序中用API的连接检享目录:
bool  NetConnect(char *netPath,char *user,char *pwd)
{
      NETRESOURCE  NetRes;
      memset(&NetRes, 0, sizeof(NETRESOURCE));
      NetRes.dwScope=RESOURCE_CONNECTED;
      NetRes.dwType=RESOURCETYPE_ANY;
      NetRes.dwDisplayType=RESOURCEDISPLAYTYPE_GENERIC;
      NetRes.dwUsage=RESOURCEUSAGE_CONNECTABLE;
      NetRes.lpRemoteName=netPath;
      DWORD result=WNetAddConnection2(&NetRes,pwd,user,0);
      return(result==0);      // 0: 正常
}
断开连接的子程序:
//相当于DOS命令  net  use  \\ip\share$  /delete
bool  NetCancel(char *netPath)
    {
          DWORD result=WNetCancelConnection2(netPath,0,true);
          return(result==0);      // 0: 正常
}
//———————————————-
连接时间较短是比较安全的,太长就不安全了;

用共享方式,连接数可能有限,ACCESS的库一般只能供2/3人共用,多了,就慢了;
最终不得不用SQL SERVER了,它支持远程共享;

好象不可以.见意还是看看MS-SQL MY-SQL 的资料.

  • Filed under: C++ Builder
  • 我用CB6通过ODBC连接MYSQL数据库后,用DBGrid对一个表中的数据进行显示时,字符字段中的内容均为"?",不知是什么原因,请大家帮助一下啦,谢谢.
    字符字段设置的类型为char,在线等…

    字符集编码问题,和字段类型没有关系,建议MySQL以“UTF-8”来处理所有信息

    字符集编码问题,MySQL一般用UTF-8编码

    我试了一下,在MYSQL的设置中将字符集已经改成了UTF-8了,但是还是只能显示"?"呀,这是为什么呢?

    把原有内容删除,包括表,或者删除全部纪录后,修改表属性以支持UTF-8

    谢谢了,问题解决了,在ODBC那里把字符集设置一下就好了,马上给分.

  • Filed under: C++ Builder
  • 点击DBGrid列头,要对字段排序,一般只要将列头对应字段名送入 ADODataSet1->Sort即可,
    但我表打开方式是"UseServer/Keyset", 不能用改Sort方法,只好重新打开,SQL中跟order by 子句,
    void __fastcall TForm1::DBGrid1TitleClick(TColumn *Column)
    {
          void * SavePlace=ADODataSet1->GetBookmark();    // 原Bookmark
          String zd=Column->FieldName;
          ADODataSet1->Close();
          ADODataSet1->CommandText="select * from Project order by "+zd;
          ADODataSet1->Open();

          ADODataSet1->GotoBookmark(SavePlace);
          ADODataSet1->FreeBookmark(SavePlace);
    }
    列头排序是成功了,但这样回不到重新打开前的记录位置外,为何?
    不知Bookmark是按什么记忆原来的位置?

    C/C++ code
    // 没看到你用的是TADODataSet,不过用法一样的,把名字换下就ok了

    主要问的是:用Bookmark,为何回不到原来的位置?Bookmark是按什么记忆原来的位置?

    C/C++ code
    // Bookmark想到于保存当前的记录指针 // 你数据集都关闭了。记录指针也丢失了 // 所以下次打开数据集的时候,并不能找到这个记录指针

    支持楼上。顺便接个分!

    唯一的做法就是根据ID号定位了

  • Filed under: C++ Builder
  • 用BCB制作的软件连接扫描仪器,起初扫描仪器获取的数据是在内存里,我需要将这些数据存储到数据库的表格里面,这些表格该如何建立,如果要多次扫描,那么这些数据需要多张表来存储,这需要怎么做?

    你的描述太简单了,不知道一次扫描和多次扫描是同一个(种)数据对象,还是多个(种)数据对象。

    图像数据可以存储在blob类型字段中,blob类型字段的读取搜索帖子就有了。

    引用 2 楼 yuanreid 的回复:
    你的描述太简单了,不知道一次扫描和多次扫描是同一个(种)数据对象,还是多个(种)数据对象。

    图像数据可以存储在blob类型字段中,blob类型字段的读取搜索帖子就有了。


    扫描的是同一种数据对象 ,数字类型,不是图像

    如果是同一种那就沒有必要建立多個表了
    直接在數据庫裏建好一張表
    在每次掃描的時候對只要抓到掃描儀的數據,就把抓到的數據做insert

    一种类型的对象或数据可以用一个表存储。根据自己的业务逻辑来构建表结构吧。

    回答楼上的 能否实现每扫描依次 存储一张表,虽然每张表的格式一样只有数据不一样,最后如果选择报表打印的话,数据库连接应该怎么选择~~

    每次掃描存一張表那你數據庫裏的表不是越來越多
    其實完全可以用一個表來解決的
    你建立兩個字段
    字段1:你掃描儀獲得的數據
    字段2:自己定義的標誌比如時間什麽的

    每次插入的時候再插入數據的時候同時把標誌字段也插一下

    在打印報表的時候先根據條件去搜索

    比如 你18號 插入的數據字段1:aaa  字段2:2008-11-18

    在打印的時候就用select 字段1 from table where 字段2 = '2008-11-18'

    用這樣的方式去篩選數據

    要是连续几次扫描是同一天呢

    嘿嘿 那就用時間啊
    字段1  字段2
    aaa    08:00:00
    bbb    09:00:00
    ccc    10:00:00

    如果要出報表說9點后的 那就是select 字段1 form table where 字段2 > '09:00:00'

    C/C++ code
    // 看上去好像不是程序逻辑的实现问题 // 你可以先把需要的存储的数据列出来 // 然后把这些需要存储到数据库中的数据间的相互关系搞清楚,内部关联啥的 // 弄清楚后,就知道自己到底要建立啥逻辑结构的数据表 // 接下来的过程就是用ADO组控件向SQL服务器发送sql语句了

    回楼上滴~ 我不要用SQL建
    如何建立动态表呢~~

    C/C++ code
    // 怎么个动态建呢? // 你的表不是要建立在数据库中么?

    BCB能否利用自带的数据库 动态建表~~

    C/C++ code
    // 自带的数据库指的是Pradox么? // 这个可以,但你用这个做程序,可能要发布和BDE相关的dll

    对对 就是paradox 能否说的具体一点 如何用paradox动态建表~~

    C/C++ code
    // 你的新的另1贴已经给你回复了,请查看

  • Filed under: C++ Builder
  • 我做了一个Socket服务器,使用ADOConnection1连接SQLserver数据库,当接收到客户端请求的时候执行下面的代码:

    String __fastcall TFrmBankServer::GetUserInfo(String userid)
    {
        double yhjbl,zdybl;
        AnsiString sql,cnnd,sobj,infostr,m_grys,bcyj,m_grysa;
        TDateTime yhjdt,dt,zdydt;
        int j;
    try
    {
        infostr="";
        pQuery->SQL->Clear();
        sql="select * from V_UserAllinfo where A_cardnum ='"+Trim(userid)+"' and C_year='2009'";
        pQuery->SQL->Add(sql);
        pQuery->Open();
        if(!pQuery->Eof)
        {
          if (Trim(pQuery->FieldByName("C_grjkbz")->AsString)=="1")
              return infostr="6  05";
          if (Trim(pQuery->FieldByName("C_tgbz")->AsString)!="0")
              return infostr="6  02";
        }else{
        infostr="6  01";
        }
    }catch(Exception &e){
    infostr="6  99";
    return infostr;
    }
    return infostr;
    }

    运行一段时间(正常)后,无论更改Trim(userid)的值,总是抛出异常,查看数据库进程信息好像是执行了SQL语句,不知道什么原因,请大家帮忙!!!!!!!!

    try
    {
        infostr="";
        pQuery->Close();//———–
        pQuery->SQL->Clear();
        ……

    暫時沒有發現程序什麽大問題
    不過Socket接數據的時候不知道你用的是什麽方式 阻塞還是非組塞
    要考慮大量數據近來時候處理速度的問題

    比如我們以前做了個項目有很多Client 數據量很大 很多數據同時進來 因爲Sql server處理insert也是需要時間的 所以可能會造成數據上的錯誤

    pQuery->Close();

    必须使用这个关掉吗?

    我的client数据量不是很大,就是在发生错误后,不重启就一直是这个错误

    可以试试先

    close是关闭对象,并释放对象打开数据集所占用的内存空间.但是你这个异常错…似乎不象是这个问题
    不過一般都是先close+open

    引用 1 楼 wenlianjie 的回复:
    重启,好像是重新连接数据库后就正常了?

    有可能是跟数据库的连接出现了问题,你可以试试每次执行SQL前,重置一下数据库的连接

    C/C++ code
    AnsiString sql_str; sql_str = "….."; Query1->Close(); Query1->SQL->Clear(); Query1->SQL->Add(sql_str); …. pQuery->Open();

    ADOConnection1,每次都重置连接是不是影响效率呀?

    引用 8 楼 wenlianjie 的回复:
    ADOConnection1,每次都重置连接是不是影响效率呀?

    或者在执行SQL错误后,手工进行重联。

    类型问题遇到过.

    看看是不是Close那里报错. 因为DataSetProvider会让Query关闭的时候报错的.

    Close明显调用还是不调用没关系.
    Clear的时候, 会调用关闭的, 内部是调用SetActive(fasle)来实现.

    C/C++ code
    /* 问题解决了没有? 你的GetUserInfo如果会执行多次的话,很可能造成多个数据库连接会话 嗯,最好还是每次执行sql语句,都按照 Close() ; SQL->Clear(); SQL->Add(..); Open(); //ExeSQL(); 另外你的循环里面少了 pQuery->Next();否则很可能进入死循环了! */

    C/C++ code
    //不好意思,你是if语句,我以为是while 呢

    问题是没有先关闭一下查询控件!应该是这个顺序:
    TQuery->Close();
    TQuery->SQL->Clear();
    ….
    TQuery->Prepare();
    TQuery->Open();
    if( TQuery->RecordCOunt > 0 )
    {
    }

    TQuery->Close();

    每次都要先关闭!
    另外,你这个代码写太不规范了!!

    问题解决了,后来还是将银行前置机跟数据库服务器直连了,直连后就没有问题了,可能原来是由于访问数据库阻塞造成的

  • Filed under: C++ Builder
  • 我想DBEdit想数据库中加数据,若有与以前重复的数据则弹出这样的错误“已有重复记录”然后返回。代码我已经写好,但是点击新增时,修改的总是数据库中存在的数据,这段代码怎么改好?
          if( DBEdit1->Text.IsEmpty())
      {
        Application->MessageBox("采面名称不能为空!", "优耐电子", MB_OK +
            MB_ICONINFORMATION);
            return;
        }
              if( DBEdit2->Text.IsEmpty())
      {
        Application->MessageBox("分机号不能为空!", "information", MB_OK +
            MB_ICONINFORMATION);
            return;
        }
              if( DBEdit3->Text.IsEmpty())
      {
        Application->MessageBox("支架号不能为空!", "information", MB_OK +
            MB_ICONINFORMATION);
            return;
        }
              if( DBComboBox1->Text.IsEmpty())
      {
        Application->MessageBox("位置不能为空!", "information", MB_OK +
            MB_ICONINFORMATION);
            return;
        }
        if( ADOTable2->FieldByName("采面名称")->AsString== DBEdit1->Text&&ADOTable2->FieldByName("分机号")->AsString==DBEdit2->Text&&ADOTable2->FieldByName("支架号")->AsString==DBEdit3->Text&&ADOTable2->FieldByName("位置")->AsString==DBComboBox1->Text)
        {
          Application->MessageBox("该设置已存在!请重新设置", "information", MB_OK +
              MB_ICONINFORMATION);
              ADOTable2->Next();
            return;
          }
      ADOTable2->Append();

    }

    不要用這個寫法
    這個功能在insert數據庫之前先做select
    select * from table where xx = '+DBEdit1->Text+' and yy = '+DBEdit2->Text+' ….
    然後去判斷select出來的結果集裏有沒有數據
    如果沒有做insert
    如果有提示已經存在

    楼上的正解
    ADOQuery1->Close();
    ADOQuery1->SQL->Clear();
    ADOQuery1->SQL->Add("select * from table where xx = '+DBEdit1->Text+' and yy = '+DBEdit2->Text+' …. ");
    ADOQuery1->Open();
    if(ADOQuery1->RecordCount>0)
        {
        MessageBox(this->Handle,"该设置已存在!请重新设置","提示",MB_OK);
        return;
        }

    有这样的错误怎么改?“将varchar值‘+DBEdit2->Text+'转化为数据类型为int的列时发生语法错误

    引用 4 楼 springworker 的回复:
    有这样的错误怎么改?“将varchar值‘+DBEdit2->Text+'转化为数据类型为int的列时发生语法错误

    没看懂
    有字符不能转整型吧

    ‘+DBEdit2->Text.ToInt()+'
    或者先
    try
    {
    DBEdit2->Text.ToInt();
    }
    catch(…)
    {
    //异常处理
    }

    要看字段的類型
    varchar等等用 '"+dbedit->text+"'
    int用 "+dbedit->text+"

    ADOTable2->FieldByName("分机号")->AsInteger=DBEdit2->Text.ToInt();

    还有个问题
    我设了2个控件
    一个增加  一个提交
    在增加里的代码是ADOTable2->Append();
    在提交的代码就是判断了

    但是一运行是点击增加,然后我想向 DBEdit控件中写入的时候
    DBEdit又出现数据库里的数据
    只有再点击增加按钮后才不出现上面的那种情况
    这是什么问题?

    你是不是绑定了DBEdit啊,就用个Edit算了,要不你把两个代码贴出来,看看

    對數据庫的操作就老老實實的寫法算了
    用幾個Edit
    在insert之前先做select去判斷有沒有重復
    如果有就return掉
    沒有就執行
    不要用數據源去綁控件

  • Filed under: C++ Builder
  • 想实现红外光谱数据查询显示,目标化合物相关信息查询。每条光谱数据最大可达1000个double型数据。
    由于采集到的光谱数据格式不同,准备以first(光谱图起始波数位置),last(光谱图结束波数位置),count(光谱数据点个数),MaxY(光谱数值的最大值),MinY(光谱数值的最小值)来对光谱数据进行标志。
    希望数据库高手建议一个比较好的解决方案,最好编程易上手,数据库稳定性要好。
    access好像不适合。

    mysql足矣

    同时要显示目标化合物的分子结构等信息,我准备用图形来存储,用Mysql合适吗?

    C/C++ code
    //嗯,省钱就用MySQL呢,或者偷偷的用MS SQL(不建议呢)

    引用 3 楼 dxqxiaoqiang 的回复:
    同时要显示目标化合物的分子结构等信息,我准备用图形来存储,用Mysql合适吗?

    MySQl可以存储图片类型。前面有帖子专门问过如何读取MySQL的图片类型字段,你可以搜索一下,供参考。

    http://topic.csdn.net/u/20081105/18/39bd0eca-9d7b-4570-87e5-9507211f8674.html

    上面的贴子我已经看过了,只是没有留言,潜水ING~~
    谢谢楼上的了~~

    yuanreid 能不能给点CB6.0+mysql的一点入门知识,没用过mysql…不好意思.

    只要用过BDE或ADO就可以了,接口都是相同的。

    MSSQL +ADO ,用流文件存图片

    Sql SERVER

    随便用把,,  按照BC 联接数据库向导做就好

    准备用Mysql了,准备再发一个贴征求BC+mysql的完美解决方案.

  • Filed under: C++ Builder
  • 各位大侠 我现在能用ADO 连接数据库 但是我想把数据库的内容显示到程序上要怎么做

    具体从数据库中在怎么读出代码呢 ??

    分少 但是肯定给

    thwen0101  你的这个方法 知识让数据显示在Edit1和Edit2 上 并没有使用到DBGrid啊 

                  不是我想要的
                  不过 还是非常感谢你  thwen0101

    C/C++ code
    /* 放个DataSource,DBGrid到界面上 设置DBGrid的DataSource为DataSource1 设置DataSource1的DataSet为ADOQuery1 前面你点击ADOQuery1的ConnectString ,build生成数据库连接串 将那条sql语句添加到ADOQuery1的SQL属性里面 然后设置ADOQuery1的Active为true,若不出现以外,在DBGrid1中应该 可以看到数据了。 */

    楼上的对的,
    将DBGRID列对应数据库中的字段

    jxw1987628  感谢你 我现在已经能在DGRrid中显示出我数据库的记录头了

    不过我更想知道 我怎么能把所有的记录 用BCB代码来完成呢 ?

    C/C++ code
    AnsiString strSQL="SELECT * FROM table";//要执行的sql语句,查询table里的所有记录 ADOQuery1->Close(); ADOQuery1->SQL->Clear(); ADOQuery1->SQL->Add(strSQL); ADOQuery1->Open(); //若是DML语句或者其他不返回结果记录集的sql语句,这里应该是ExeSQL方法 /* 建议你还是找本 C++Builder数据库编程的书籍吧,数据库方面的内容比较多 呵呵,一个帖子也很难解决所有的问题,多看看书,还有帮助文档! */

    jxw1987628  朋友感谢你的建议 我会找点书看看

                不过我是想问 ADOQuery1->Open(); 返回的字符集 能显示到DBGrid上吗
                我现在别的东西都还会点 就把内容显示到DBGrid上 还不会
                书上都是写的很概念 没有真正的代码可以参考 现在还没时间去买书 还着急 只能求助向你们这样的好心人了

    DBGRID绑定之后,就不用写代码了,这样就行了
    ADOQuery1->Close();
    ADOQuery1->SQL->Clear();
    ADOQuery1->SQL->Add(strSQL);
    ADOQuery1->Open(); //若是DML语句或者其他不返回结果记录集的sql语句,这里应该是ExeSQL方法

    如果用纯代码设置的话,用ado,可以这样
    先用ADOConnection连接数据库,设置connectionString属性

    C/C++ code
    AnsiString conn="Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;"; conn+="Initial Catalog=数据库名;Data Source=(local)"; ADOConnection1->ConnectionString = conn; ADOTable1->Connection=ADOConnection1; ADOTable1->TableName="表名"; DataSource1->DataSet=ADOTable1; DBGrid1->DataSource=DataSource1;

    刚敲的代码,大概就是这样,如果有错别字你校正一下。

    为什么只有在桌面  放上TTable  我DateSource的DataSet中下来箭头里才能设置TTable

    如果往DataSet中 写入ADOQuery1 就会报错  DataSource1:Circular datalinks arenot allowed

    Circular datalinks arenot allowed
    自己翻译一下这句话
    “循环的数据链接不可用”
    说明数据源循环链接了,自己找一下哪里有错

    恩 我貌似找到了

    朋友们 我的好用了  非常感谢你们对我的帮助 我会更加努力 呵呵

  • Filed under: C++ Builder
  • 我在本机上安装了SQL2005SERVER,库中建了五个表,其中有两具表有BLOB字段,存放
    客户上传的项目文件,随着试验数据的增多,BCB6编的主窗体显示越来越慢,程序运行后,
    要8秒后,才出现主窗口.我逐个用GetTickCount()求时间差的办法分年出慢的原因是
    一个含BLOB字段的表,有80条记录,我只好先打开四个表,强制显示出主窗体后,再打开
    这个慢表,只算能应付.
        马上发布后,多个客户从服务器上访问表(服务器也是普通电脑),岂不更慢,
    如果一开始就这么慢,如何交差呢.

    一。数据库的信息库没有得到及时更新,产生大量I/O(此项一般会很要命。查看DBCC命令吧)。
    二。设置一些常用字段的Index。通过Index检索查询。
    三。表结构最好放置一个主键字段。

    最好限制一下上传文件的大小 ,如小于1M,不然服务器那受得了,
    显示主窗口后再加载数据要好点

    1.设了一个自增的ID做了主键;
    2.查询并不多,用了四个DBGRID显示表内容
    3.DBCC没用过,不知怎用

    那就设置一些Index

    慢的原因与曾存放过大的BLOB文件有关,
    我重新建了慢表的结构,一下子显示就快了,
    等传过大文件后,又不正常了

    那样的话的确是因为产生大量的I/O问题。
    只能设置一个瓶颈减小文件大小,来减小I/O量。

    我想出来了:
    解决慢的另一个办法把BLOB字段单独做一个表,用字段ID关联,
    这样主表与从表不涉及BLOB,速度应该快多了;

    的确是,程序一下子快多了,说明 BLOB字段内容太大会使用表打开奇慢;

    恩,既然是dbgrid中显示,blog字段可以放到另外的表中。

  • Filed under: C++ Builder
  •   那天见有个用delphi做的程序,他在程序中使用了一个oracle的控件,这个控件可以不用在本地安装oracle的客户端,直连到服务器上,请问有这样的c++builder的控件吗? 我使用的是c++builder6.0

    ADO不行吧

    好像么见过~~

    不知道

    安装Oracle的客户端其实就是几个DLL,不安装直接复制DLL到本地即可
    —————

    以下是转贴内容
    http://www.cnblogs.com/suyuan/archive/2008/05/21/1203733.html

    首先,在安装ORACLE服务器的机器上搜索下列文件,
    oci.dll
    ocijdbc10.dll
    ociw32.dll
    orannzsbb10.dll
    oraocci10.dll
    oraociei10.dll
    sqlnet.ora
    tnsnames.ora
    classes12.jar
    ojdbc14.jar
    制作成压缩文件,配置目标计算机使用。

    1.将oracleinstantclient.rar解压缩到一个目录, 如d:\oracleinstantclient

    2.配置d:\oracleinstantclient的tnsnames.ora文件,只需要修改其中的服务器地址、服务名称和端口。

    3、配置环境变量,在PATH变量中加入d:\oracleinstantclient

    4、注册表加入下面键值     

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]

    "LD_LIBRARY_PATH"="d:\OracleInstantClient"

    "NLS_LANG"="AMERICAN_AMERICA.ZHS16GBK"

    "TNS_ADMIN"="d:\OracleInstantClient"

    5、如果是ASP.NET应用,则要为ASPNET用户分配d:\oracleinstantclient文件夹的读写权限。

    通过上面的设置后,即可实现免安装ORACLE客户端,连接到ORACLE数据库服务器。

    也可以将上面解压缩后的文件和手动过程制作成安装包,实现自动安装。

    注意:

    1、用上面的方法,连接oracle9.2,应该也没有问题。

    2、如果使用JDBC连接,需要到官网下载instantclient-jdbc-win32-10.1.0.2.zip:  包含JDBC  Driver的包

    MARK

    —那天见有个用delphi做的程序,他在程序中使用了一个oracle的控件,这个控件可以不用在本地安装oracle的客户端,直连到服务器上,请问有这样的c++builder的控件吗? 我使用的是c++builder6.0

      我认为这样的控件是存在的,但不是一个控件,而是一组。
        在C++Builder连数据库最常用的有三种方式:1.ADO 2.BDE 3.MIDAS控件 
        只是要把数据库程序做成三层。本地用的是客户程序,服务器上安装ORACLEHE 和应用服务器程序,那么就不用在本地安装oracle的客户端,这样也可以直接连接到服务器。若不是采用多层结构的话,程序会因为找不到Oracle Listener服务(没安装ORACLE客户端)而连不上Oracle数据库.
    控件主要是用MIDAS控件: 
      1.客户端程序用的控件主要有:TDCOMConection, TClientDataSet和数据集感知控件。
      2.应用服务器程序用的控件主要有:TDataSetProvider, TTable or TADOQuery ,TSession 和TDatabase
    具体做法可以上网查相关例子,应该有。

    这人也太那个了吧,自己写个不就成了

    写个配置文件,连接装有数据库的地址不就可以了吗?

    用ODAC就可以了。

  • Filed under: C++ Builder
  • 类别

    最新

    标签

    链接


    存档