Click here to Skip to main content
15,867,308 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
PHP
<?php

$file = "/tmp/kok.bin";

$fp = fopen ($file, 'rb')
    or die ("File $file cannot be opened.");


$data = fread ($fp, filesize($file));
    or die ("Could not read data from file $file");

# Create the format for unpacking the header data
$header_format = 
    'Cid/' .            # Grab 1 byte      
    'Cnumber/' .        # Grab 1 byte
    'CIdentifier/' .    # Grab 1 byte     
    'CTime/' .          # Grab 8 bytes 
    'L# of Records/' .  # Grab 1 byte , number of target in a packet
    'SHeader Size/' .   # Grab 4 bytes
    'SRecord Size';     # Grab 2 bytes

# Unpack the header data
$header = unpack ($header_format, $data);
$targetRecord =$header_format['L# of Records'];

    
# Create the format for unpacking the data that describes the format of the records in the file
$record_format = 
    'CField Name/' .    # Grab 1 byte
    'fField Type1/' .   # Grab 4 bytes 
    'fField Type2/' .   # Grab 4 bytes
    'fField Type3/' .   # Grab 4 bytes 
    'fField number/' .  # Grab 4 bytes           
    'fdistance/' .      # Grab 4 bytes
    'CField id /'       # Grab 1 byte 
    'iField Precision/' # Grab 4 bytes the size of the Field Data
    'SField Data';      # Grab x bytes 
for ($offset = 0; $offset < strlen ($data); $offset ++) {
    print_r (unpack ("$record_format", $data));
}
?>




1 first unpack $header_format to get 'L# of Records' for every packet.(have a total of 200 packets)
2 unpack  $record_format  'L# of Records' times
$record_format = 
     CField Name/' .    # Grab 1 byte
    'fField Type1/' .   # Grab 4 bytes 
    'fField Type2/' .   # Grab 4 bytes
    'fField Type3/' .   # Grab 4 bytes 
    'fField number/' .  # Grab 4 bytes           
    'fdistance/' .      # Grab 4 bytes
    'CField id /'       # Grab 1 byte 
    'iField Precision/' # Grab 4 bytes
    'SField Data';      # Grab x bytes 

3 Step 1 and 2 are for one packet from the file.
4 Repeat 1-3 until end of file is reached.  


What I have tried:

for ($offset = 0; $offset < strlen ($data); $offset += 32) {
    $unpackeddata= unpack ("@$offset/$header_format", $data);
    print "";
    print_r ($unpackeddata);
    print "";
}
Posted
Updated 31-Aug-18 23:24pm
v9
Comments
Patrice T 30-Aug-18 10:31am    
We have no idea what you talk about.
Give context.
We are not NSA, we can't see your screen or access your HDD
Member 13967442 30-Aug-18 13:59pm    
I tried to explain a bit,added more code

As far as I understand you have a file with a header followed by a number of recordsets. Then you have to adjust the offset accordingly while processing your data:
PHP
$header = unpack ($header_format, $data);
// Note that your code used header_format here wrongly
$numRecords = $header['L# of Records'];
// Assuming these are what the name indicates
$offset = $header['SHeader Size'];
$recordSize = $header['SRecord Size'];
for ($i = 0; $i < $numRecords; $i++)
{
    $record = unpack ($record_format, $data, $offset);
    $offset += $recordSize;
}
This requires setting up the unpack() format strings properly so that they match the data in the file. The CTime field for example looks suspicious because I have no idea how a time value can be stored in 8 bits.

[EDIT]
If there are multiple packets beginning with a header you have to put the above into an outer loop:
PHP
$offset = 0;
$data_len = strlen($data);
while ($offset < $data_len)
{
    // Get package header
    $header = unpack ($header_format, $data, $offset);
    // Number of records in this package
    $numRecords = $header['L# of Records'];
    // Size of each record for this packet
    $recordSize = $header['SRecord Size'];
    // Adjust offset to point to first record of this packet
    $offset += $header['SHeader Size'];
    // Process records of this packet
    for ($i = 0; $i < $numRecords; $i++)
    {
        $record = unpack ($record_format, $data, $offset);
        // Adjust offset to point to next record of this packet
        $offset += $recordSize;
    }
    // $offset points to next package header if not at end of data
}
[/EDIT]
 
Share this answer
 
v2
Comments
Patrice T 31-Aug-18 7:26am    
This is a .dbf file.
The OP happily mistaking the records set with what is in fact the fields headers.
The first header start at offset 32 and each header is size 32.
Jochen Arndt 31-Aug-18 7:41am    
That was not quite clear for me because the provided format strings did not match the DBF structures.

But my solution still shows how to iterate adjusting the offset as necessary.

More important then:
It seems that he used the DBF data type characters in his PHP unpack format strings instead of using the corresponding PHP identifiers.
Member 13967442 31-Aug-18 10:26am    
The file is not a .dbf file, it is a .bin file with each packet having header size 18. and 'CTime/' is wrong 'dTime', since it is timestamp
Patrice T 31-Aug-18 11:01am    
Where does this line came from ?
"# Get the top of the dbf file header"
Member 13967442 31-Aug-18 11:15am    
sorry that is a mistake
Quote:
I need to unpack the rest of the packet.

I think your problem is that you unpack always at beginning of file
PHP
unpack ("$record_format", $data)

instead of the position of what you want to unpack.
File header start at offset 0
First Field header start at offset 32
Second Field header start at offset 64
...


But $data is the whole file.
.dbf - Wikipedia[^]

[Update]
NO!
It is the loop start at 32 and it is not header_format:
PHP
for ($offset = 0; $offset < strlen ($data); $offset += 32) {
    $unpackeddata= unpack ("@$offset/$header_format", $data);
    print "";
    print_r ($unpackeddata);
    print "";
}


[Update]
Anything about .dbf in solution is wrong because
PHP
# Get the top of the dbf file header

in original code is wrong too.
 
Share this answer
 
v3
Comments
Patrice T 31-Aug-18 0:40am    
Use Improve question to update your question.
So that everyone can pay attention to this information.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900