2016-07-16 7 views
2

델파이 (RAD Studio)에서 프로젝트를 만들고 있습니다. 일부 행에는 데이터베이스 테이블에 저장된 이미지가 있습니다. 런타임에 이미지를 추출하고 (TMemoryStream의 Array를 사용하고있는) 이미지를 frxReport에 표시하고 싶습니다.런타임에 데이터베이스에서 TMemoryStream에 여러 이미지를 저장하고 나중에 추출하는 방법

내 코드

공공 변수은 TStream은

로 선언 다음과 같이

Stream2 : Array of TStream; i,k: integer

코드 세그먼트 MainForm에 배치하고 frxReport을 보여줄 것으로 예상된다보기 버튼을 클릭 이벤트에 대한.

`

procedure TFrmMain.btnViewClick(Sender: TObject); 
begin 
    i := 0; 
    k := 0; 
    UniTable1.SQL.Text := 'Select * from userplays order by id'; 
    UniTable1.Execute; 

    rowcount := UniTable1.RecordCount; 

    SetLength(myid, rowcount); 
    SetLength(mydesc, rowcount); 
    SetLength(myimg, rowcount); 
    SetLength(Stream2, rowcount); 

     while not UniTable1.Eof do 
     begin 
     try 
      Stream2[k] := TMemoryStream.Create; 
      myid[k] := UniTable1.FieldByName('id').Value; 
      Stream2[k] := UniTable1.CreateBlobStream(TBlobField(UniTable1.FieldByName('image')), bmRead); 
      mydesc[k] := UniTable1.FieldByName('description').Value; 

     UniTable1.Next; 
     inc(k); 

     finally 
      //Stream2[k].Free; 
     end; 

     end; 

     frxUserDataSet1.RangeEnd := reCount; 
     frxUserDataSet1.RangeEndCount := rowcount; 
     frxReport1.ShowReport; 
     i := 0; 
end; 

`

그러나이 방법 Stream2 어레이에 대한 이미지를로드하지 않는다. 친절하게 방법을 알려

procedure TFrmMain.frxReport1GetValue(const VarName: string; var Value: Variant);

`

Graphic := TJPEGImage.Create; 
Graphic.LoadFromStream(Stream2[j]); 
TfrxPictureView(frxreport1.FindObject('Picture1')).Picture.Graphic := Graphic; 

` 에서 frxRaport에 표시 할 JPEGImage 배열이 다음 사용 된 경우, 그러나 그것은 문제가 될 것 JPEGImage의 배열을 사용하는 옵션이 있습니다 이 작업을 수행.

+0

정확히 델파이 버전은 무엇입니까 ??? 내 제안 : 일부 파일 컨테이너를 사용하십시오 : .TAR 또는 .ZIP 또는 무엇이든 - 파일을 넣은 다음 파일을 데이터베이스 BLOB에 저장하십시오. 예를 들어 Delphi XE2에서는 디스크를 건드리지 않고도 TStream을 통해 메모리 내장 ZIP을 만들 수 있습니다. 그래서 당신은 직접적으로 많은 파일을 포함하기 위해 TMemoryStream 또는 TBLobStream을 사용할 수 있습니다. –

+0

델파이 버전 XE-3 –

+0

을 사용하고 있습니다. 그 방법은 당신을 위해 가야하고, 스트림을 통해 메모리 내 지퍼를 만들어 DB에 저장하는 방법입니다. 아주 먼 코드지만 몇 가지 클래스 메서드를 언급 https://github.com/the-Arioch/avemey.com/blob/master/zexmlss/src/zeZippyXE2.pas –

답변

3

그러나이 방법은 먼저 새로 TMemoryStreamStream2[k]에 만들어 할당하는 현재의 코드에서 Stream2 배열

에 대한 이미지를로드되지 않습니다

 Stream2[k] := TMemoryStream.Create; 

는 당신이를 던지고있다 TMemoryStream 떨어져 (메모리 누출 생성) 생성 한 BLOB 스트림으로 바꾸기 :

 Stream2[k] := UniTable1.CreateBlobStream(TBlobField(UniTable1.FieldByName('image')), bmRead); 

하지만 BLOB 스트림을 읽지 않습니다. 여기

내가 id, descriptionimage 함께 개최하는 레코드를 정의하는 것이 좋습니다 다음 레코드의 배열을 대신 별도의 세 가지 것,

var 
    blobstream: TStream; 
    Stream2: array of TMemoryStream; 

    .... 
    // read 'id', 'description' and 'image' fields to respective arrays 
    while not UniTable1.Eof do 
    begin 
    myid[k] := UniTable1.FieldByName('id').Value; 
    mydesc[k] := UniTable1.FieldByName('description').Value; 

    blobstream := UniTable1.CreateBlobStream(TBlobField(UniTable1.FieldByName('image')), bmRead); 
    try 
     Stream2[k] := TMemoryStream.Create; 
     Stream2[k].LoadFromStream(blobstream); 
    finally 
     blobstream.Free; 
    end; 

    UniTable1.Next; 
    inc(k); 
    end; 

Btw는 (안된)에 while 루프 다시 쓴입니다 배열. 3 개 대신 하나의 어레이 만 관리하는 것이 훨씬 간단합니다.

+0

안녕하세요, 작동하지만 frxReport에서 동일한 이미지 (특히 memorystream 배열의 마지막 이미지)를 보여줍니다. Graphic.LoadFromStream (Stream2 [j]); 그것은 전체 배열에 같은 이미지 (마지막 하나)를 저장하는 것 같습니다. –

+0

@ NinadAvasare 데이터베이스에 이미지가 하나만 저장되어 있지 않으면 그 방법을 알 수 없습니다. 디버거에서 코드를 단계별로 실행하면 예를 들어 볼 수 있습니다. 각 라운드마다 'id'값이 변경됩니까? 또는'LoadFromStream()'이후의'Stream2 [k]'의 크기? –

+0

안녕하세요 Tom, 예 id 값이 루프의 각 라운드마다 변경됩니다. 또한 ID와 DESC가 모두 성공적으로 업데이트되고 fastreport에서 출력을 표시합니다. 문제는 스트림을 저장하고로드 할 때 이미지 필드에만 문제가 있기 때문입니다. –

2

당신의 상황에서 가장 분명한 것은 기존의 DataSet (Unitable1)을 frxReport의 DataBand에 직접 연결하는 것이라고 생각합니다. 나는 어쨌든 그것을 만들었 기 때문에 Unitx1로 설정된 DataSet 속성으로 frxDBDataset 대신 frxUserDataset을 사용해야하는 이유를 알지 못합니다.

정말 개체 목록이 필요한 경우 다른 접근 방식을 취할 것입니다. 여러 개의 전역 변수가보기 흉하고 위험합니다 (i, k ...)

나는 당신의 데이터를 보유하는 클래스를 생성하고 System.Generics.Collection에서 TObjectList와에이 데이터를 채울 것

: 다음

procedure TMain.Button2Click(Sender: TObject); 
var 
DataRow: TMyDataPack; 
List: TObjectList<TMyDataPack>; 
Num: integer; 
CurrentImage: TImage; 
CurrentDescription: String; 
CurrentId: integer; 
begin 
    UniTable1.SQL.Text:='SELECT * FROM Userplays'; 
    UniTable1.Open(); 

List:=TObjectList<TMyDataPack>.Create; 
while not (UniTable1.Eof) do 
    begin 
    DataRow:=TMyDataPack.Create(UniTable1); 
    if(DataRow.Loaded) then 
    List.Add(DataRow); 
    UniTable1.Next; 
    End; 


for Num:=0 to List.Count do 
    begin 
    CurrentDescription:=List[Num].MyDescription; 
    CurrentImage:=List[Num].MyImage; 
    CurrentId:=List[Num].MyId; 
    //List[Num].MyImage.Picture.SaveToFile('Some'+IntToStr(Num)+'.bmp'); 
    // You might save it to file then... 
    end; 
    end; 

    end. 

: 기본 코드에서 다음

unit DataPack; 

interface 
uses ExtCtrls...System.SysUtils; 

type 

TMyDataPack = class(TObject) 

    private 
    Query: TFDQuery; //O r TUniQery 
    _MyId: Integer; 
    _MyDescription: String; 
    _MyImage: TImage; 
    _Loaded: Boolean; 
    function LoadData: boolean; 
    protected 
    public 
    constructor Create(Data: TFDQuery); //Or Uniquery 
    property MyId: Integer read _MyId; 
    property MyDescription: String read _MyDescription; 
    property MyImage: TImage read _MyImage; 
    property Loaded: Boolean read _Loaded; 
end; 

implementation 

{ TMyDataPack } 

constructor TMyDataPack.Create(Data: TFDQuery); 
begin 
    Inherited Create; 
    Query:=Data; 
    _Loaded:=true; 
    if not (LoadData) then 
    _Loaded:=false; 

end; 

function TMyDataPack.LoadData: boolean; 
var 
Stream: TStream; 
begin 
Stream:= TStream.Create; 
    Stream:=Query.CreateBlobStream(TBlobField(Query.FieldByName('image')), bmRead); 

try 
    _MyImage:=TImage.Create(nil); 
    _MyImage.Picture.Bitmap.LoadFromStream(Stream); 
    _MyDescription:=Query.FieldByName('description').AsString; 
    _MyId:=Query.FieldByName('CategoryId').AsInteger; 
except on E: Exception do 
    begin 
    FreeAndNil(Stream); 
    FreeAndNil(_MyImage); 
    Exit(false); 
    end; 

end; 
FreeAndNil(Stream); 
Result:=true; 
end; 

end. 

ObjectList를 추가로 전달하십시오. 마지막에 해제하는 것을 잊지 마십시오.

예를 들어 동일한 데이터를 사용하는 다른 데이터베이스를 사용해야하는 경우 클래스 팩터 리를 만들어 확장 할 수도 있습니다. 이미지가 실제로 BMP 또는 Jpg인지 확인합니다. SQL로 설정하지 않고 쿼리를 전달하고 TobjectList를 속성으로 가져올 수도 있습니다.