Delphi中对Oracle存取RTF文档
点击次数:65 次 发布日期:2008-11-09 08:38:00 作者:源代码网
|
源代码网推荐 源代码网推荐 对于纯文本,可以简单地将其分割成若干个串,分别存储到VARCHAR(2000)字段中即可。在查询时 可以使用LIKE比较,从而达到全文检索的目的。为了保留换行等段落信息,应当将回车换行(#13#10) 也作为串的一部分进行保存。数据录入时可以提供Memo控件(不是DBMemo)进行录入,然后顺序连接各行,当连接成的串临近2000个字符(单字节字符)长度时,就存入一条记录,然后对剩余的行重复上述操作。这样,最终将纯文本存成若干长度不超过2000的VARCHAR(2000) 字段中。这里需要另外开辟字段 用于存储文本编号和子序号,以便区分不同的文本和读取文本时顺序连接所有的子串。查询纯文本时, 就可以象查询普通的VARCHAR 字段一样,可以使用LIKE,也可以使用等号“ =”(几乎不需要使用)。 需要注意的是,可能用户提供的关键字正好被存储在不同的子串中,这时是查询不到的。因此,在设计时应当考虑存储重复的串。例如,每个子串中仅有前1900个字符是有效字符,最后100 个字符用于存储 下一个子串的前100 个字符。这样就避免了关键字被分开的情况。唯一的不足是,必须限制用户输入的 查询关键字长度不得超过100 个字符(50个汉字),但这很正常,算不上不足。 源代码网推荐 源代码网推荐 事实上,同样可以利用这一技巧对 RTF文档进行存取和查询。这时,用于录入和显示 RTF文档的是 RichEdit控件(不是DBRichEdit),而不再是Memo控件。对于 RTF文档的存取,不能象存取纯文本那样 通过Memo的属性Lines.Strings[Index]进行操作(尽管RichEdit控件具有相同的属性),因为这样做就 无法保存文档的格式了。需要利用的是RichEdit的两个方法:SaveToFile和LoadFromFile。需要了解的 是, RTF文件中用纯字符描述字体、字号、文本等各种格式信息和内容信息。因此,存储和提取时可以 视为纯文本进行操作。但对于查询,就不能直接用LIKE加关键字的方式进行。因为 RTF文档中的每一个 汉字都是用特殊的表示方法存储,只有单字节字符是原样存储。所以在查询时要对关键字进行处理才能 用在查询语句中。 源代码网推荐 源代码网推荐 在测试这个例子之前,必须有如下的数据结构,这里以Oracle创建表的 SQL语句形式给出: 源代码网推荐 源代码网推荐 (* 源代码网推荐 CREATE TABLE TEST( { 表名为 TEST } 源代码网推荐 DOCID NUMBER NOT NULL, { 文档编号 } 源代码网推荐 DOCNAME VARCHAR(40) NOT NULL, { 文档标题 } 源代码网推荐 SUBID NUMBER NOT NULL, { 文档子编号 } 源代码网推荐 TEXT VARCHAR(2000) NOT NULL, { 子文档内容 } 源代码网推荐 PRIMARY KEY(DOCID, SUBID)); { 联合主键 } 源代码网推荐 *) 源代码网推荐 源代码网推荐 下面是程序实例中的主要部分: 源代码网推荐 源代码网推荐 { ... ... } 源代码网推荐 源代码网推荐 const 源代码网推荐 BufSize = 2000; { 串的最大容量 } 源代码网推荐 源代码网推荐 type 源代码网推荐 TBuffer = array [1..BufSize] of Char; { 串缓存 } 源代码网推荐 TFileOfChar = file of Char; { 字符类型文件 } 源代码网推荐 源代码网推荐 TChnChar = string[2]; { 汉字字符类型 } 源代码网推荐 源代码网推荐 { SQL查询,返回首记录首字段的值 } 源代码网推荐 function SelectSQL(S: string): Variant; 源代码网推荐 begin 源代码网推荐 Result := NULL; 源代码网推荐 with TADOQuery.Create(Application) do try 源代码网推荐 Connection := FMain.ADOConnection1; 源代码网推荐 SQL.Append(S); 源代码网推荐 SQL.SaveToFile("c:a.txt"); 源代码网推荐 Open; 源代码网推荐 Result := Fields[0].AsVariant; 源代码网推荐 finally 源代码网推荐 Free; 源代码网推荐 end; 源代码网推荐 end; 源代码网推荐 源代码网推荐 { 下面的函数将RTF文档存入数据库 } 源代码网推荐 function RTFToDB(ARichEdit: TRichEdit; { 文档容器 } 源代码网推荐 DocName: string; { 文档标题 } 源代码网推荐 ATable: TADOTable { 操作的表 } 源代码网推荐 ): Boolean; { 返回类型 } 源代码网推荐 const 源代码网推荐 TmpFileName = "c:x.rtf"; { 临时文档 } 源代码网推荐 var 源代码网推荐 DocID, SubID, L: Integer; { 局部变量 } 源代码网推荐 S: string; { 串 } 源代码网推荐 F: TFileOfChar; { 字符文件 } 源代码网推荐 Buf: TBuffer; { 文本缓存 } 源代码网推荐 begin 源代码网推荐 ARichEdit.Lines.SaveToFile(TmpFileName);{ 先存入文件 } 源代码网推荐 AssignFile(F, TmpFileName); { 打开文件 } 源代码网推荐 Reset(F); 源代码网推荐 try 源代码网推荐 DocID := { 产生新的文档编号 } 源代码网推荐 SelectSQL("SELECT NVL(MAX(DOCID) 1, 101) FROM TEST"); 源代码网推荐 with ATable do if not Active then Active := True;{ 确认表打开 } 源代码网推荐 SubID := 0; { 初始化子编号 } 源代码网推荐 while not EOF(F) do begin 源代码网推荐 Inc(SubID); 源代码网推荐 BlockRead(F, Buf, BufSize, L); { 读取两千个字符 } 源代码网推荐 S := Buf; 源代码网推荐 SetLength(S, L); { 取实际读取到的字节数 } 源代码网推荐 with ATable do begin { 增加一条子文档 } 源代码网推荐 Append; 源代码网推荐 FieldByName("DOCID").AsInteger := DocID; 源代码网推荐 FieldByName("DOCNAME").AsString := DocName; 源代码网推荐 FieldByName("SubID").AsInteger := SubID; 源代码网推荐 FieldByName("TEXT").AsString := S; 源代码网推荐 Post; 源代码网推荐 end; 源代码网推荐 end; 源代码网推荐 Result := True; { 存储成功 } 源代码网推荐 except 源代码网推荐 Result := False;{ 存储失败 } 源代码网推荐 end; 源代码网推荐 CloseFile(F); { 关闭文件 } 源代码网推荐 DeleteFile(TmpFileName);{ 删除文件 } 源代码网推荐 end; 源代码网推荐 源代码网推荐 源代码网推荐 { 下面的函数从数据库中读取RTF文档,并在指定的容器中显示 } 源代码网推荐 function RTFFromDB(ARichEdit: TRichEdit;{ RTF文档容器 } 软件开发网 www.mscto.com 源代码网推荐 DocName: string; { 文档标题 } 源代码网推荐 AQuery: TADOQuery { 操作的数据集 } 源代码网推荐 ): Boolean; { 返回类型 } 源代码网推荐 const 源代码网推荐 TmpFileName = "c: empx.rtf"; { 临时文件 } 源代码网推荐 var 源代码网推荐 S: string; { 局部串变量 } 源代码网推荐 F: TFileOfChar; { 字符文件 } 源代码网推荐 Buf: TBuffer; { 串缓存 } 源代码网推荐 I, L: Integer; { 局部变量 } 源代码网推荐 begin 源代码网推荐 ARichEdit.Clear; { 清除当前显示的内容 } 源代码网推荐 AssignFile(F, TmpFileName); { 关联文件 } 源代码网推荐 try 源代码网推荐 Rewrite(F); { 打开文件,准备写入从数据库读出的数据 } 源代码网推荐 with AQuery do begin 源代码网推荐 Active := False; { 关闭数据集 } 源代码网推荐 SQL.Clear; { 重建SQL语句 } 源代码网推荐 SQL.Append("SELECT SUBID, TEXT FROM TEST WHERE DOCNAME = """ 源代码网推荐 DocName """ ORDER BY SUBID"); 源代码网推荐 Open; { 打开数据集 } 源代码网推荐 if RecordCount <> 0 then begin { 确认数据集非空 } 源代码网推荐 First; { 移到首记录-子文档 } 源代码网推荐 repeat { 读出一条子文档并写入文件 } 源代码网推荐 S := FieldByName("TEXT").AsString; 源代码网推荐 L := Length(S); 源代码网推荐 for I := 1 to L do Buf[I] := S[I]; 源代码网推荐 BlockWrite(F, Buf, L); 源代码网推荐 Next; 源代码网推荐 until EOF; 源代码网推荐 end; 源代码网推荐 end; 源代码网推荐 CloseFile(F);{ 关闭文件 } 源代码网推荐 ARichEdit.Lines.LoadFromFile(TmpFileName);{ 从文件中装入RTF文档 } 源代码网推荐 Result := True; { 读取成功 } 源代码网推荐 except { 读取失败 } 源代码网推荐 try CloseFile(F); except end; 源代码网推荐 Result := False; 源代码网推荐 end; 源代码网推荐 DeleteFile(TmpFileName); { 删除临时文件 } 源代码网推荐 end; 源代码网推荐 源代码网推荐 { 下面的函数将汉字单字转换成RTF中表示的形式。 } 源代码网推荐 { 如表示汉字“国”的是ASCII(b9)和ASCII(fa),这里是十六进制; } 源代码网推荐 { 那么在 RTF文件中对“国”字的表示占用了 8个字节: } 源代码网推荐 { "b9"fa } 源代码网推荐 { 因此,需要在查询之前进行转换。由于表示方法中含有Delphi用于 } 源代码网推荐 { 字符串的分解符:单撇号“"”,因此在转换时需要考虑这一点, } 源代码网推荐 { 否则就不能构造出正确的 SQL查询语句 } 源代码网推荐 function ChnCharToRTFCode(Ch: TChnChar): string; 源代码网推荐 var 源代码网推荐 C1, C2: Char; 源代码网推荐 O1, O2: Byte; 源代码网推荐 S: string; 源代码网推荐 begin 源代码网推荐 C1 := Ch[1]; 源代码网推荐 C2 := Ch[2]; 源代码网推荐 O1 := Ord(C1); 源代码网推荐 O2 := Ord(C2); 源代码网推荐 S := Format("""""%2X", [O1]) Format("""""%2X", [O2]); 源代码网推荐 Result := Lowercase(S);{ 转换为小写 } 源代码网推荐 end; 源代码网推荐 源代码网推荐 { 根据需要检索的关键字转换成LIKE中使用的串。 } 源代码网推荐 { 这里用于区别汉字的方法是根据编码。 } 源代码网推荐 { 按照Windows 中的双字节编码规则,对于双字节字符 } 源代码网推荐 { 如汉字字符,是由两个字节构成,其中第一个字节是 } 源代码网推荐 { 引导字符。汉字引导字符的ASCII 码大于 127,因此 } 源代码网推荐 { 可以根据此特点来区分汉字和单字节字符。 } 源代码网推荐 function MakeLikeRTFString(StrToFind: string): string; 源代码网推荐 var 源代码网推荐 I: Integer; 源代码网推荐 ChnChar: TChnChar; 源代码网推荐 S: string; 源代码网推荐 begin 源代码网推荐 S := ""; 源代码网推荐 I := 0; 源代码网推荐 while I < Length(StrToFind) do begin 源代码网推荐 Inc(I); 源代码网推荐 if Integer(StrToFind[I]) >= $80 then begin{ 汉字的首字节一定不小于128 } 源代码网推荐 ChnChar := StrToFind[I] StrToFind[I 1]; 源代码网推荐 Inc(I); 源代码网推荐 S := S ChnCharToRTFCode(ChnChar); 源代码网推荐 end else begin{ 单字节字符 } 源代码网推荐 S := S StrToFind[I]; 源代码网推荐 if StrToFind[I] = """" then S := S StrToFind[I];{ 单撇号的特殊处理 } 源代码网推荐 end; 源代码网推荐 end; 源代码网推荐 Result := S; 源代码网推荐 end; 源代码网推荐 源代码网推荐 { 构造对关键字进行全文检索的查询语句 } 源代码网推荐 function MakeLikeString(StrToFind: string): string; 源代码网推荐 var 源代码网推荐 S: string; 源代码网推荐 begin 源代码网推荐 S := MakeLikeRTFString(StrToFind); 源代码网推荐 S := "SELECT DISTINCT DOCNAME FROM TEST WHERE TEXT LIKE ""%" S "%"""; 源代码网推荐 Result := S; 源代码网推荐 end; 源代码网推荐 源代码网供稿. |
