Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Konwertowanie textu do ciągu binarnego
Forum PHP.pl > Forum > Przedszkole
iwosz
Witam,

nie mogę znaleść odpowiedzi na moje pytanie, które jest dość proste jednak z tego co widzę sprawia jakies problemy, bo nie mogę nic znaleść w sieci worriedsmiley.gif

Jak można w PHP 5.3 w optymalny sposób przekonwertować text np. "Ala ma kota" na ciąg binarny, tak aby zapisać to wszystko w bazie danych w polu BLOB w taki sposób aby można było to odczytać z powrotem jako text? W efekcie chcę uzyskać odpowiednia wartość aby zapisać do DB (Firebird) jako BLOB sub_type binary.

"W sposób optymalny" mam na myśli coś lepszego niż przeglądanie textu po każdym znaczku i konwertowanie... to nie zadziała dla dużych ilości textu. Dodatkowo taka funkcja powinna przyjmować jako parametr kodowanie w jakim jest zakodowany text dla poprawnej zamiany, mam rację?

Kombinowałem w tej sposób:
  1. for($i=0;$i<strlen($params_str);$i++){
  2. $blob_data .= sprintf("%08s ",decbin(ord($params_str[$i])));
  3. }

ale to nie działa poprawnie i wydajnie... worriedsmiley.gif

Próbowałem też czegoś takiego:
  1. $blob_data = unpack('H*', $params_str);
  2. $blob_data = base_convert($blob_data[0], 16, 2);

ale to też nie działa poprawnie...

W ASP.NET jest funkcja które przyjmuje właśnie jako parametr kodowanie oraz text i konwertuje do ciągu binarnego, jednak w PHP nie mogę znaleść odpowiednika, a wiem że się da to zrobić.

Proszę o sugestie, z czego skorzystać i jakich funkcjo użyć w tym celu. Z góry dzięki!
Crozin
1. base_convert pracuje nad tekstem i zwraca tekst, więc jest tutaj kompletnie nieodpowiedni.
2. Praca z danymi binarnymi w PHP jest wyjątkowo nieprzyjazna. Nie istnieje typ zmiennej byte/char, typ integer jest zmiennej długości (SIC!) i jedyne co nam pozostaje to... tekst. Stringi w PHP można traktować jako tablicę typu byte/char (Google: binary string).
3. Na dobrą sprawę wszystko co musisz zrobić to upewnić się, że tekst jest w odpowiednim kodowaniu (iconv, mb_convert_encoding) i traktować tekst jako dane binarne od tego momentu.
iwosz
Cytat(Crozin @ 28.09.2012, 16:22:18 ) *
3. Na dobrą sprawę wszystko co musisz zrobić to upewnić się, że tekst jest w odpowiednim kodowaniu (iconv, mb_convert_encoding) i traktować tekst jako dane binarne od tego momentu.


Rozumiem, dzięki pokombinuję w ten sposób, jednak czy text przed 'wepchnięciem' do bazy nie powinno się zamienić jawnie na ciąg binarny? Bo chodzi jeszcze o odczyt tych danych smile.gif jak czysty text wrzucam do BLOBa to odczytując mam problem bo obiekt jest długości 0:
  1. (
  2. [0] => 0
  3. [length] => 0
  4. [1] => 1
  5. [numseg] => 1
  6. [2] => 0
  7. [maxseg] => 0
  8. [3] =>
  9. [stream] =>
  10. [4] =>
  11. [isnull] =>
  12. )

Zapisuję i odczytuję według dokumentacji, korzystając z funkcji ibase* function.ibase-blob-get
Crozin
Tekst w PHP zawsze jest w formie binarnej. Jeżeli w wyniku użycia var_dump() wyświetli Ci się "5f1e" oznacza to tablicę następujących bajtów: 0x35 0x66 0x31 0x65. Jeżeli wyświetli się "01011110101" oznacza to tablicę następujących bajtów: 0x30 0x31 0x30 0x31 0x31 0x31 0x31 0x30 0x31 0x30 0x31. Jeżeli natomiast wyświetli Ci się "cześć" oznacza to tablicę następujących bajtów: 0x63 0x7a 0x65 0xc5 0x9b 0xc4 0x87.
Pamiętaj, że w każdym przypadku istotne jest kodowanie ciągu. W przypadku użycia UTF-16 w pierwszym przykładzie otrzymalibyśmy: 0x00 0x35 0x00 0x66 0x00 0x31 0x00 0x65.

Pokaż kod dodający i pobierający dane z bazy.

PS. Dlaczego nie korzystasz z PDO?
iwosz
Doczytałem że są/były problemy z odczytywaniem dużych BLOBów i trzeba to robić paczkami więc testowo czytam pierwsze 8192 bajtów, jednak moje odczytane dane nie wyglądają dobrze a wykonałem taki test (wszystko zakodowane jest w UTF-8 w PHP i w DB):

  1. $var_datablob = 'TEST1: Testowy text zapisany jako blob'; // text zapisywane do bloba i pola tekstowego 'TEST'
  2.  
  3. $blob_id = ibase_blob_create();
  4. ibase_blob_add($blob_id, $var_datablob);
  5. $blob_id_str = ibase_blob_close($blob_id);
  6.  
  7. $q = "INSERT INTO TMP_TEST(TEST, OBJ) VALUES('$var_datablob','$blob_id_str')";
  8. $d = $DB->db->exec($q);
  9.  
  10. $q = "INSERT INTO TMP_TEST(TEST, OBJ) VALUES('TEST2: Testowy text zapisany jako blob',$blob_id_str)";
  11. $d = $DB->db->exec($q);

A odczytałem tak:
  1. $q = "SELECT * FROM TMP_TEST";
  2. $d = $DB->db->query($q);
  3.  
  4. while( $row = $d->fetchRow(MDB2_FETCHMODE_OBJECT) ) {
  5. $blobinfo = ibase_blob_info($row->obj);
  6. $blob_id = ibase_blob_open($row->obj);
  7. $stringBLOB = ibase_blob_get($blob_id,8192);
  8.  
  9. echo '#' . $row->t_id . ' | ' . $row->test . ' | BLOB string: ' . $stringBLOB . '<br>';
  10.  
  11. ibase_blob_close($blob_id);
  12. }

Co dało taki wynik:
  1. #1 | TEST1: Testowy text zapisany jako blob | BLOB string: 0x0000000100000000
  2. #2 | TEST2: Testowy text zapisany jako blob | BLOB string: 4294967296

Przy czym wartość "4294967296" dostaję nie zależnie jaką wartość dodam jeśli nie będzie w ciapkach(''). Wartość "0x0000000100000000" dostaję zawsze niezależnie jaką wartość podam jeśli jest bez ciapek... więc o co tutaj chodzi!? Co dopiero mówić o konwertowaniu tego jakkolwiek...

To są "przykłady książkowe" bez żadnych moich kombinacji i powinny działać "z automatu" ale nic z tego... obsługa BLOBów w PHP dla ibase to porażka... thumbsdownsmileyanim.gif

Uff, rozgryzłem to... jednak z przykrością stwierdzam że wbudowane funkcje ibase* częściowo nie działają prawidłowo. Jednak korzystając z rad Crozin'a spróbowałem "na chama" wpakować dane do BLOB'a i się udało smile.gif Z odczytem już jest lepiej bo działa to tak jak powinno czyli mamy coś takiego:

  1. // ZAPIS
  2. $var_datablob = 'TEST1: Testowy text zapisany jako blob';
  3.  
  4. $q = "INSERT INTO TMP_TEST(TEST, OBJ) VALUES('$var_datablob','$var_datablob')";
  5. $d = $DB->db->exec($q);
  6.  
  7. // ODCZYT
  8. $q = "SELECT * FROM TMP_TEST";
  9. $d = $DB->db->query($q);
  10.  
  11. while( $row = $d->fetchRow(MDB2_FETCHMODE_OBJECT) ) {
  12. $blob_id = ibase_blob_open($row->obj);
  13. $blobinfo = ibase_blob_info($row->obj);
  14. $blobdata = ibase_blob_get($blob_id,$blobinfo[0]); // nasz text 'TEST1: Testowy text zapisany jako blob' !
  15.  
  16. echo $blobdata;
  17.  
  18. ibase_blob_close($blob_id); // to musi byc!
  19. }

Nie wiem jeszcze jak się zachowa taki odczyt (czyli całość na raz) dla na prawdę dużych danych, ponoć są z tym problemy, tak samo nie zadziała to gdy w definicji pola BLOB w bazie zadeklarujemy jawnie wielkość segmentu np:
  1. CREATE TABLE test (
  2. ID INTEGER,
  3. OBJ BLOB SUB_TYPE 1 SEGMENT SIZE 80
  4. );

Wtedy należy postępować tak jak w tym komentarzu: http://www.php.net/manual/pl/function.ibas...b-get.php#60192 i pobierać po kawałku dane zklejając końcowy wynik.

Teraz to dla mnie proste i logiczne ale wcześniej widocznie miałem jakąś zaćmę... wstydnis.gif

Jeszcze raz dzięki Crozin za pomocne wskazówki!
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.