救命,用MyDAC的存储文件到Blob字段问题!小弟使用WinXP+Delphi7+Mysql开发一套管理软件,用的是MyDAC v5.10读取Mysql。是从这里下载的Full Source版本:
http://www.2ccc.com/article.asp?articleid=4280 本来觉得非常好用,但是由于业务需要,把mysql的latin1字符集改成了utf8。
原来在latin1下读取blob字段都没有问题,但是自从改成了utf8以后,别的都非常好用,但是我现在发现MyDAC在utf8字符集下读取blob字段有问题,两个症状如下:
1. 在硬盘上一个30.5K的文件存到数据库里居然有61K,正好翻倍!
很明显,MyDAC把blob的每一个字节像处理普通文本一样,把它从ANSI转成Unicode再存入到数据库中!但这是错误的!
2. 从硬盘上读取一个Jpg文件,用MyDAC存到数据库的Blob字段中,Delphi就报错!错误停在MyDAC源代码的MemData.pas里的这个函数的raise Exception.Create(SInvalidBlobPosition);语句,整个函数如下:function TBlob.TranslatePosition(Position: integer): integer; // Ansi to Unicode
var
Piece: PPieceHeader;
CurPosAnsi, CurPosUni, i: integer;
p: IntPtr;
w: WideString;
s: string;
begin
Assert(FIsUnicode); if {$IFNDEF CLR}not SysLocale.FarEast{$ELSE}(LeadBytes = []){$ENDIF} or (Position = 0) then begin
Result := Position * 2;
Exit;
end; CurPosAnsi := 0;
CurPosUni := 0;
Piece := FFirstPiece;
while IntPtr(Piece) <> nil do begin
p := IntPtr(Integer(Piece) + Sizeof(TPieceHeader));
for i := 0 to Cardinal((Piece.Used div 2) - 1) do begin
w := Marshal.PtrToStringUni(IntPtr(Integer(p) + i * 2), 1);
s := w;
Inc(CurPosUni, 2);
Inc(CurPosAnsi, Length(s));
if CurPosAnsi = Position then begin
Result := CurPosUni;
Exit;
end;
if CurPosAnsi > Position then
raise Exception.Create(SInvalidBlobPosition);
end;
Piece := Piece.Next;
end;
raise Exception.Create(SInvalidBlobPosition);
end;
这个问题,我认为是MyDAC的一个bug,没想到收费的专业控件也这么水啊。但是小弟对Delphi理解不深刻,只会用它编一些简单的数据库软件,所以没法改这个MyDAC的源代码。哪位大哥可以帮我想想这个问题怎么解决?有能力的不妨改改MyDAC源代码试试。非常感谢!如果需要我的测试程序,请留下EMAIL,我发给你们。再次感谢!!注意,如果MyDAC想要读取utf8字符集的话,需要把TMyConnection的Options属性的Charset设为utf8,同时把Options属性的UseUnicode设为True。这步必不可少,否则它不会按照utf8的编码去读取数据库,这样读出来的数据当然不能正确显示!设定完毕以后,处理一般各种语言的文本没有任何问题,唯独不能正确存储Blob字段!
http://www.2ccc.com/article.asp?articleid=4280 本来觉得非常好用,但是由于业务需要,把mysql的latin1字符集改成了utf8。
原来在latin1下读取blob字段都没有问题,但是自从改成了utf8以后,别的都非常好用,但是我现在发现MyDAC在utf8字符集下读取blob字段有问题,两个症状如下:
1. 在硬盘上一个30.5K的文件存到数据库里居然有61K,正好翻倍!
很明显,MyDAC把blob的每一个字节像处理普通文本一样,把它从ANSI转成Unicode再存入到数据库中!但这是错误的!
2. 从硬盘上读取一个Jpg文件,用MyDAC存到数据库的Blob字段中,Delphi就报错!错误停在MyDAC源代码的MemData.pas里的这个函数的raise Exception.Create(SInvalidBlobPosition);语句,整个函数如下:function TBlob.TranslatePosition(Position: integer): integer; // Ansi to Unicode
var
Piece: PPieceHeader;
CurPosAnsi, CurPosUni, i: integer;
p: IntPtr;
w: WideString;
s: string;
begin
Assert(FIsUnicode); if {$IFNDEF CLR}not SysLocale.FarEast{$ELSE}(LeadBytes = []){$ENDIF} or (Position = 0) then begin
Result := Position * 2;
Exit;
end; CurPosAnsi := 0;
CurPosUni := 0;
Piece := FFirstPiece;
while IntPtr(Piece) <> nil do begin
p := IntPtr(Integer(Piece) + Sizeof(TPieceHeader));
for i := 0 to Cardinal((Piece.Used div 2) - 1) do begin
w := Marshal.PtrToStringUni(IntPtr(Integer(p) + i * 2), 1);
s := w;
Inc(CurPosUni, 2);
Inc(CurPosAnsi, Length(s));
if CurPosAnsi = Position then begin
Result := CurPosUni;
Exit;
end;
if CurPosAnsi > Position then
raise Exception.Create(SInvalidBlobPosition);
end;
Piece := Piece.Next;
end;
raise Exception.Create(SInvalidBlobPosition);
end;
这个问题,我认为是MyDAC的一个bug,没想到收费的专业控件也这么水啊。但是小弟对Delphi理解不深刻,只会用它编一些简单的数据库软件,所以没法改这个MyDAC的源代码。哪位大哥可以帮我想想这个问题怎么解决?有能力的不妨改改MyDAC源代码试试。非常感谢!如果需要我的测试程序,请留下EMAIL,我发给你们。再次感谢!!注意,如果MyDAC想要读取utf8字符集的话,需要把TMyConnection的Options属性的Charset设为utf8,同时把Options属性的UseUnicode设为True。这步必不可少,否则它不会按照utf8的编码去读取数据库,这样读出来的数据当然不能正确显示!设定完毕以后,处理一般各种语言的文本没有任何问题,唯独不能正确存储Blob字段!
解决方案 »
- 基础问题
- 大家帮助我好急啊....................
- 照着教程做,也不能做出来,帮我看看
- 明天考试,诚心求教,解决最后问题!感激不可言表!
- 怎样把四个表里的查询到的内容并到一个dbgrid中去显示?
- application?HWND?
- 在函数中,返回参数能否使用字符串数组?
- 网页内容自动提交!!!快要被折磨得死掉了!!!这样有什么不同!!!高手请进!!!UP有分!
- delphi中用深麼函數來實現程序暫停一小段時間?
- Delphi 如何写一个文件上载组件??????
- 请教各位大侠一个ADO的跨库查询问题
- 关于程序执行DTS包文件出现"执行已被用户取消"的问题,江湖救急阿急急!!!!!!!!
BLOB字段只能存储64K的东西,超过当然报错了,你把字段类型改成MEDIMBLOB就行了!
建议先研究下MYSQL的数据类型,不然类似错误还要犯!
var
stream: TMemorystream;
begin
if not OpenDialog1.Execute then exit;
stream := TMemorystream.Create;
stream.LoadFromFile(OpenDialog1.FileName);
stream.Position := 0; MyQuery1.SQL.Text := 'insert into `test` (pic_id, pic_name, Image) values (null, :picname, :Image)';
MyQuery1.ParamByName('picname').AsString := OpenDialog1.FileName;
MyQuery1.ParamByName('Image').LoadFromStream(stream, ftBlob); //MyQuery1.ParamByName('Image').LoadFromFile(OpenImageEnDialog1.FileName, ftBlob);
MyQuery1.Execute; stream.Free;
end;这样也不行.....
数据库用户名:test 密码:test 数据库名称:test Server:localhost
create table phototest(photo longblob default null);
但是用BCB却可以,所以我怀疑是Delphi的问题!!!
TBlobField *PB; MyQuery1.Close;
MyQuery1.SQL.Clear;
MyQuery1.SQL.Add("select * from phototest");
MyQuery1.Open;
MyQuery1.Append;
MyQuery1.Edit;
PB = (TBlobField *)MyQuery1.FieldByName("photo");
PB.LoadFromFile(Edit1.Text);
MyQuery1.ApplyUpdates;
数据库用户名:test 密码:test 数据库名称:test Server:localhost
create table phototest(photo longblob default null);
但是用BCB却可以,所以我怀疑是Delphi的问题!!!
TBlobField *PB; MyQuery1.Close;
MyQuery1.SQL.Clear;
MyQuery1.SQL.Add("select * from phototest");
MyQuery1.Open;
MyQuery1.Append;
MyQuery1.Edit;
PB = (TBlobField *)MyQuery1.FieldByName("photo");
PB.LoadFromFile(Edit1.Text);
MyQuery1.ApplyUpdates;