2016-10-04 76 views
5

Mam tablicę liczb całkowitychzapis danych binarnych do pliku, dosłownie

Array 
(
    [0] => Array 
     (
      [0] => 1531412763 
      [1] => 1439959339 
      [2] => 76 
      [3] => 122 
      [4] => 200 
      [5] => 4550 
      [6] => 444 
     ) 
... 

I tak dalej, przypuszczam, jeśli patrzę na to tak, jakby to była baza danych - elementów tablicy peryferyjnego są wiersze a elementami wewnętrznych tablic są kolumny.

Chcę zapisać te informacje w pliku, aby móc je później odzyskać, ale chcę zapisać je jako dane binarne, aby zaoszczędzić miejsce. Zasadniczo, jeśli napiszę pierwszą liczbę całkowitą z przykładu 1531412763 do pliku, zajmie to 10 bajtów, ale jeśli mógłbym zapisać go jako liczbę całkowitą ze znakiem, zajęłoby to 4 bajty.

Przyjrzałem się wielu innym odpowiedziom, które wszystkie sugerują użycie fwrite, których nie rozumiem w jaki sposób używać w taki sposób?

+0

[by] (http://php.net/manual/en/function.pack.php)? – Zimmi

+0

Jeśli * naprawdę * potrzebujesz zaoszczędzić miejsce, czemu nie skompresować danych? Równie dobrze może w tym momencie. – Andrew

+0

@Zimmi tak, to dokładnie to, czego potrzebowałem, ale czy muszę wywoływać 'paczkę' na każdą pojedynczą wartość lub czy istnieje łatwiejszy sposób? –

Odpowiedz

3

Do zapisywania danych binarnych w pliku można używać funkcji pack() i unpack(). Pack wygeneruje ciąg binarny. Jako wynik jest ciąg, można połączyć ints w jeden ciąg znaków. Następnie napisz ten ciąg jako linię do pliku.

W ten sposób można łatwo odczytać z file(), co spowoduje umieszczenie pliku w tablicy linii. Następnie po prostu unpack() każda linia, a ty masz oryginalną tablicę z powrotem.

tak:

$arr = array(
    array (1531412763, 1439959339), 
    array (123, 456, 789), 
); 

$file_w = fopen('binint', 'w+'); 

// Creating file content : concatenation of binary strings 
$bin_str = ''; 
foreach ($arr as $inner_array_of_int) { 
    foreach ($inner_array_of_int as $num) { 
     // Use of i format (integer). If you want to change format 
     // according to the value of $num, you will have to save the 
     // format too. 
     $bin_str .= pack('i', $num); 
    } 

    $bin_str .= "\n"; 
} 

fwrite($file_w, $bin_str); 
fclose($file_w); 


// Now read and test. $lines_read will contain an array like the original. 
$lines_read = []; 
// We use file function to read the file as an array of lines. 
$file_r = file('binint'); 

// Unpack all lines 
foreach ($file_r as $line) { 
    // Format is i* because we may have more than 1 int in the line 
    // If you changed format while packing, you will have to unpack with the 
    // corresponding same format 
    $lines_read[] = unpack('i*', $line); 
} 

var_dump($lines_read); 
+1

A jeśli każdy wiersz zawiera dokładnie tę samą liczbę elementów, których nie potrzebujesz nawet nowych linii, wystarczy obliczyć długość wiersza po przekonwertowaniu na plik binarny, a następnie 'fread ($ handle, $ length)'. –

+0

Absolutnie! Zoptymalizuj format, tak jak zasugerowałeś w ostatnim komentarzu w pytaniu. – Zimmi

+0

Korzystając z tej metody, zamiast zapisywać zwykły tekst udało mi się zaoszczędzić sporo miejsca. Od "2,72 GB" do "400 MB", to jest redukcja o 6,8 razy! –