Zapisywanie pola BLOB jako text do bazy danych

0

Witam,
mam bazę danych w mssql, z tabelą w której jedno z pól jest typu image.
Czyli pole binarne.

Potrzebuje zrobić inserta do tej tabeli, tak aby te pole otrzymało wartość 0xFFFF0000000000FF000000000000, czyli żeby zapisywało się tak:
screenshot-20170522115600.png

używam do tego celu parametru typu BLOB:

ADataBase.Kwerenda.ParamByName('grfw_Formatowanie').LoadFromStream(Stream, ftBlob);

gdzie Stream to różne opcje, które testowałem np.

Stream := TStringStream.Create('FFFF0000000000FF000000000000');

sęk w tym, że nie zapisuje mi do pola w bazie tego co chcę tylko jakoś chyba konwertuje sobie na bity po swojemu i zapisuje co innego.
Jak zapisać toco potrzebuję?

1

http://stackoverflow.com/questions/26103437/delphi-load-image-save-as-blob-in-a-sql-database
a tu masz dla ADO
http://stackoverflow.com/questions/11773986/how-to-insert-image-into-database-using-tadoquery-component-only

W przypadku postgresql i ZeosLib trzeba nieco pokombinować z transaction isolation level ale to już nieco inna bajka ;)

0

Dzięki, ale cow tym linku jest ciekawego co mogło by mi pomóc?
Raczej jest problem z załadowaniem tego co potrzebuję do streama, aniżeli z blobem do bazy...

0

W moim starutkim (2006) delphi używam CreateBlobStream. Działa mi na serwerach 2005, 2008 i 2012. Na innych nie sprawdzałem, ale chyba też będzie OK.

0

Wydaje mi się, że podajecie mi informacje, jak zapisać do bazy pole typu BLOB,
a to po części wiem jak się robi,
sękw tym aby zapisało mi konkretną wartość taką jaką sobie życzę (stały ciąg bajtów).

0

Masakra ... tylko po co wyważasz otwarte drzwi? Jak rozumiem masz pole na bazie którego typ jest jako VARBINARY(Max) / image tak? Jeśli tak to w linkach podanych przeze mnie masz gotowy kod jak plik np JPG zapisać do strumienia i przekazać do bazy danych ... z czym konkretnie masz problem? Czy chodzi o to, że masz stringa w postaci 'FFFF0000000000FF000000000000' i chcesz go zapisać do bazy w tej postaci jako binarkę?

0
baszta1 napisał(a):

sęk tym aby zapisało mi konkretną wartość taką jaką sobie życzę (stały ciąg bajtów).

Przecież do streama, obojętnie od tego co w nim jest, możesz wstawić w dowolne jego miejsce to, co chcesz. Nie rozumiem, z czym masz problem.

0

Typ nie varbinary lecz** IMAGE**.

I potrzebuję zapisać ciąg bajtów FFFF0000000000FF000000000000, a nie obrazek. Co jeszcze mogę wyjaśnić?

0

Ech wołam @abrakadaber bo ja nie mam siły tego tłumaczyć może jemu się będzie chciało ;)

0

Wydaje mi się, że dość dokładnie opisałem problem oraz załączyłem grafikę, więc problem jest, ale własnie potrzebna pomoc konkretna w rozwiązaniu, a nie odpowiedzi typu, zapisuj sobie do streama co chcesz, a potem do bazy.

0
baszta1 napisał(a):

Wydaje mi się, że dość dokładnie opisałem problem oraz załączyłem grafikę, więc problem jest, ale własnie potrzebna pomoc konkretna w rozwiązaniu, a nie odpowiedzi typu, zapisuj sobie do streama co chcesz, a potem do bazy.

Czyżbyś chciał mieć w streamie coś innego, a w bazie coś innego? :-)
Ale może przyda Ci się trochę kodu od naszych przyjaciół ze wschodu:

function HexChar1(Ch : Char) : Byte;
  begin
    Ch := UpCase(Ch);
    if (Ch <= '9') then
      Result := Ord(Ch) - Ord('0')
    else
      Result := Ord(Ch) - Ord('A') + 10;
  end;

  function HexToStr(const s : String) : String;
  var
    Len, i           :  Integer;
    Ch               : Byte;
    NibbleH, NibbleL : Byte;
  begin
    Len := Length(s);
    SetLength(Result, Len shr 1);
    for i := 1 to Len shr 1 do begin
      NibbleH := HexChar1(s[i shl 1 - 1]);
      NibbleL := HexChar1(s[i shl 1]);
      Ch      := NibbleH shl 4 or NibbleL;
      Result[i] := Chr(Ch);
    end;
  end;

nawet zrymowało mi się :-)

0

OK, dzięki Dziadu, jest trop że to coś z HEXami.

chodzi o to, że podaje do streama np. to: FF682000000000FF000000000000
a zapisuje mi PRZEKONWERTOWANE NA HEXY: 0x46463638323030303030303030304646303030303030303030303030

a ja chcę żeby zachowało się to co podaję na wejściu - jak zapisuję przykładowo wartość do Streama podałemw pierwszym poście.

Zapomniałem też dodać, że używam FireDaca.

0

Zdaje mi się, że program, którego używasz (i z którego pochodzi załączona przez Ciebie grafika) sam robi przekonwertowanie na potrzeby wyświetlenia wyniku. Przepisz sobie tą kolumnę IMAGE ( a przynajmniej jej początek) na zwykłe pole tekstowe, np varchar. Zrób to programowo - odczyt do streama i zapis z niego do drugiej kolumny. Może zobaczysz coś innego.

2

FF682000000000FF000000000000 to REPREZENTACJA SZESNASTKOWA tego, co zawiera w sobie obrazek. TAK TEGO NIE ZAPISZESZ. Każde 2 znaki z tego ciągu reprezentują JEDEN BAJT z obrazka. Np. FF to bajt o wartośc 255, 68 to bajt o wartości 104. To co chcesz zapisać powinno mieć postać

var s: string;
begin
s := #$FF#$68#$20#$00#$00#$00#$00#$FF#$00#$00#$00#$00#$00#$00
Stream := TStringStream.Create(s);
ADataBase.Kwerenda.ParamByName('grfw_Formatowanie').LoadFromStream(Stream, ftBlob);
end;

taki zapis #$FF powoduje, że do zmiennej s jest wstawiany znak o kodzie FF szesnastkowo a nie dwie litery F. Rozumiesz? Poza tym to co widzisz w edytorze to nie jest cały obrazek tylko jego pierwsze 16 bajtów.

0

:)
wtedy w polu ląduje takie coś:

0x2324464623243638232432302324303023243030232430302324303023244646232430302324303023243030232430302324303023243030

screenshot-20170522141038.png

poprzednio doszedłem do tego, że F konwertuje mi na 46 itp (co by mówiło wg tablicy ASCII, że** F to jest CHR(char) = 46 HEX**)

czyli zamiast wstawić mi chary jak na wejściu, konwertuje mi na hexy.
Program do sql mgmt studio i wyswietla poprawnie, wiec cos zle robie po stronie wstawiania.

0

title

0

dobra, @abrakadaber wpadł i pozamiatał, jego propozycja była trafna, po prostu z rozpędu wstawiłem ciąg w klamerki i potraktowało całość jako stringa.

czyli moim problemem było zapisanie tego jako:

StringStream := TStringStream.Create(#$FF#$68#$20#$00#$00#$00#$00#$FF#$00#$00#$00#$00#$00#$00);

cóż, czlowiek sie uczycałe zycie :)

dzieki wszystkim

0

Jeszcze odpowiadając szybko dla @wloochacz, nie mam wplywu na strukturę bazy (jest dość leciwa), jest to baza 'zastana'. I wszyscy wiedzą (chyba?), że Image jest deprecated, i lepiej używać czegoś innego. dzieki, pozdrawiam

0

To tylko dodam, że chodziło mi o coś np takiego:

var s: string;
begin
   s := 'FF682000000000FF000000000000';
   Stream := TStringStream.Create(HexToStr(s));
   ADataBase.Kwerenda.ParamByName('grfw_Formatowanie').LoadFromStream(Stream, ftBlob);
end;

ale zdaje się, że @baszta1 nie zrozumiał :-(.

0

tylko, że w Delphi nie ma w standardzie funkcji HexToStr

0
abrakadaber napisał(a):

tylko, że w Delphi nie ma w standardzie funkcji HexToStr

Podałem ją w tym wątku. Przeczytaj go od początku.

0

Dziadu, testowałem Twoją funkcję, ale ona zwracała jawny string, więc wynik był inny niż oczekiwany.

0

Nie wiem, co rozumiesz przez "jawny string", a raczej nie wiem, co rozumieć przez "niejawny string". W moim starym Delphi wszystkie stringi są widoczne dla programisty, jeśli tylko chce to zobaczyć. Co do Twojego sprawdzania, to, no cóż, SOA#1.

0

Dla przyszłych pokoleń i zamknięcia tematu - kto chce to sobie niech przetestuje :)

procedure TAppForm.Button6Click(Sender: TObject);

  function HexChar1(Ch : Char) : Byte;
  begin
    Ch := UpCase(Ch);
    if (Ch <= '9') then
      Result := Ord(Ch) - Ord('0')
    else
      Result := Ord(Ch) - Ord('A') + 10;
  end;

  function HexToStr(const s : String) : String;
  var
    Len, i           :  Integer;
    Ch               : Byte;
    NibbleH, NibbleL : Byte;
  begin
    Len := Length(s);
    SetLength(Result, Len shr 1);
    for i := 1 to Len shr 1 do begin
      NibbleH := HexChar1(s[i shl 1 - 1]);
      NibbleL := HexChar1(s[i shl 1]);
      Ch      := NibbleH shl 4 or NibbleL;
      Result[i] := Chr(Ch);
    end;
  end;

var
  s, s2: string;
  Stream, Stream2: TStringStream;
begin
  s := 'FF682000000000FF000000000000';
  s2 := #$FF#$68#$20#$00#$00#$00#$00#$FF#$00#$00#$00#$00#$00#$00;
  Stream := TStringStream.Create(HexToStr(s));
  Stream2 := TStringStream.Create(s2);

  try
    ShowMessage('stream: ' + Stream.DataString);
    ShowMessage('stream2: ' + Stream2.DataString);
  finally
    Stream.Free;
    Stream2.Free;
  end;
end;
0

A to o to Ci idzie. Wyjaśniam:
W uproszczeniu, u małomiękkiego (inaczej niż w Delphi) znak o wartości 0 jest końcem stringa. Małomiękki przyjmuje, że za nim nic już nie ma. Znaku końca też nie pokazuje. A ShowMessage używa funkcji DrawText z biblioteki małomiękkiego. Ale przecież jak chce się to zobaczyć, to da się to zobaczyć. Np w RichEdit.

1 użytkowników online, w tym zalogowanych: 0, gości: 1