Delphi 从长二进制数据中检索 JPG - JPEG 错误 #53
Delphi Retrieve JPG From Long binary data - JPEG error #53
我将许多 JPEG 图像作为 Long 二进制数据添加到 Access DB 中。现在我想使用 Delphi 代码将这些图像检索到 TImage
中。
对于这项工作,我写了下面的代码,但在 运行 之后它给了我一个 JPEG 错误 #53 错误。我在 Google 中搜索了这个错误代码,并尝试了一些解决方案,例如将图片另存为新的 JPG 格式,但这并没有改变任何东西。
此外,我发现了从数据库中检索图像的不同代码,但它们都给了我相同的 JPEG 错误 #53 错误。
问题出在哪里?
procedure RetrieveImage;
var
Jpg : TGraphic;
Stream: TStream;
query : string;
Field: TBlobField;
Begin
Stream := nil;
Jpg := nil;
query := 'Select JPGFile From Table Where Name=' + QuotedStr(SoftName);
Try
With ADOQuery do
Begin
Try
SQL.Clear;
SQL.Add(query);
Open;
Field := TBlobField(FieldbyName('JPGFile'));
Stream := CreateBlobStream(Field,bmRead);
Jpg := TJpegImage.Create;
Jpg.LoadFromStream(Stream);
MainForm.PictureBox.Picture.Graphic:= Jpg;
Finally
Close;
End;
End;
Finally
Stream.Free;
Jpg.Free;
End;
End;
编辑:
我使用 C# 代码将 JPG 文件插入数据库(以下代码已简化):
// Insert Data to Access tables
private void InsertToTable(string connectionString, string query)
{
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
try
{
connection.Close();
using (OleDbCommand command = new OleDbCommand(query, connection))
{
connection.Open();
using (OleDbDataReader reader = command.ExecuteReader())
{
reader.Close();
}
command.Cancel();
}
connection.Close();
}
finally
{
connection.Close();
}
}
}
// Insert Image into database
private void SaveToDataBase(string jpegPath)
{
//jpegPath example is: (C:\Image.jpg)
string FilePath = Application.StartupPath + directory + dbName;
string MDBConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + FilePath + "; Jet OLEDB:Engine Type=5";
// Convert Image to binary
var image = File.ReadAllBytes(jpegPath);
InsertToTable(MDBConnStr, $"INSERT INTO Table JPGFile VALUES('{image}')");
}
在您的 C# 代码中,为什么要使用 ExecuteReader()
来执行 INSERT
语句?您应该改用 ExecuteNonQuery()
。
更重要的是,您实际上并没有将 image
字节数组的内容插入数据库,这就是 Delphi 的 TJPEGImage
稍后无法加载数据的原因.您的 SQL 查询被创建为 interpolated 字符串,但是您的 {image}
表达式不会像您认为的那样将原始字节插入到查询中。即使是这样,这也不是将原始字节插入“长二进制”字段的正确方法。
您需要改用参数化查询。在command.Parameters
集合中添加一个OleDbParameter
,将image
数据传入数据库,在这里你将它的DbType
属性设置为Binary
,它的OleDbType
属性 到 Binary
、LongVarBinary
或 VarBinary
,它的 Value
属性 到你的 image
字节数组。然后,您可以在 SQL 语句中引用该参数。
参见 Configuring parameters and parameter data types, especially the section on Using parameters with an OleDbCommand or OdbcCommand。
试试像这样的东西:
// Insert Image into database
private void SaveToDataBase(string jpegPath)
{
//jpegPath example is: (C:\Image.jpg)
// Convert Image to binary
var image = File.ReadAllBytes(jpegPath);
string FilePath = Application.StartupPath + directory + dbName;
string MDBConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + FilePath + "; Jet OLEDB:Engine Type=5";
using (OleDbConnection connection = new OleDbConnection(MDBConnStr))
{
connection.Open();
using (OleDbCommand command = new OleDbCommand("INSERT INTO Table JPGFile VALUES(?)", connection))
{
command.Parameters.Add("@Image", OleDbType.LongVarBinary).Value = image;
command.ExecuteNonQuery();
}
}
}
但是请注意,OLEDB 中的二进制参数最多限制为 8000 字节。
我将许多 JPEG 图像作为 Long 二进制数据添加到 Access DB 中。现在我想使用 Delphi 代码将这些图像检索到 TImage
中。
对于这项工作,我写了下面的代码,但在 运行 之后它给了我一个 JPEG 错误 #53 错误。我在 Google 中搜索了这个错误代码,并尝试了一些解决方案,例如将图片另存为新的 JPG 格式,但这并没有改变任何东西。
此外,我发现了从数据库中检索图像的不同代码,但它们都给了我相同的 JPEG 错误 #53 错误。
问题出在哪里?
procedure RetrieveImage;
var
Jpg : TGraphic;
Stream: TStream;
query : string;
Field: TBlobField;
Begin
Stream := nil;
Jpg := nil;
query := 'Select JPGFile From Table Where Name=' + QuotedStr(SoftName);
Try
With ADOQuery do
Begin
Try
SQL.Clear;
SQL.Add(query);
Open;
Field := TBlobField(FieldbyName('JPGFile'));
Stream := CreateBlobStream(Field,bmRead);
Jpg := TJpegImage.Create;
Jpg.LoadFromStream(Stream);
MainForm.PictureBox.Picture.Graphic:= Jpg;
Finally
Close;
End;
End;
Finally
Stream.Free;
Jpg.Free;
End;
End;
编辑:
我使用 C# 代码将 JPG 文件插入数据库(以下代码已简化):
// Insert Data to Access tables
private void InsertToTable(string connectionString, string query)
{
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
try
{
connection.Close();
using (OleDbCommand command = new OleDbCommand(query, connection))
{
connection.Open();
using (OleDbDataReader reader = command.ExecuteReader())
{
reader.Close();
}
command.Cancel();
}
connection.Close();
}
finally
{
connection.Close();
}
}
}
// Insert Image into database
private void SaveToDataBase(string jpegPath)
{
//jpegPath example is: (C:\Image.jpg)
string FilePath = Application.StartupPath + directory + dbName;
string MDBConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + FilePath + "; Jet OLEDB:Engine Type=5";
// Convert Image to binary
var image = File.ReadAllBytes(jpegPath);
InsertToTable(MDBConnStr, $"INSERT INTO Table JPGFile VALUES('{image}')");
}
在您的 C# 代码中,为什么要使用 ExecuteReader()
来执行 INSERT
语句?您应该改用 ExecuteNonQuery()
。
更重要的是,您实际上并没有将 image
字节数组的内容插入数据库,这就是 Delphi 的 TJPEGImage
稍后无法加载数据的原因.您的 SQL 查询被创建为 interpolated 字符串,但是您的 {image}
表达式不会像您认为的那样将原始字节插入到查询中。即使是这样,这也不是将原始字节插入“长二进制”字段的正确方法。
您需要改用参数化查询。在command.Parameters
集合中添加一个OleDbParameter
,将image
数据传入数据库,在这里你将它的DbType
属性设置为Binary
,它的OleDbType
属性 到 Binary
、LongVarBinary
或 VarBinary
,它的 Value
属性 到你的 image
字节数组。然后,您可以在 SQL 语句中引用该参数。
参见 Configuring parameters and parameter data types, especially the section on Using parameters with an OleDbCommand or OdbcCommand。
试试像这样的东西:
// Insert Image into database
private void SaveToDataBase(string jpegPath)
{
//jpegPath example is: (C:\Image.jpg)
// Convert Image to binary
var image = File.ReadAllBytes(jpegPath);
string FilePath = Application.StartupPath + directory + dbName;
string MDBConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + FilePath + "; Jet OLEDB:Engine Type=5";
using (OleDbConnection connection = new OleDbConnection(MDBConnStr))
{
connection.Open();
using (OleDbCommand command = new OleDbCommand("INSERT INTO Table JPGFile VALUES(?)", connection))
{
command.Parameters.Add("@Image", OleDbType.LongVarBinary).Value = image;
command.ExecuteNonQuery();
}
}
}
但是请注意,OLEDB 中的二进制参数最多限制为 8000 字节。