PHP - Iterate through file and break out chunks of text for JSON

47
March 16, 2019, at 01:30 AM

I have a file on a server that I need to parse and build a JSON object to return. I am using PHP.

The file contents look something like this:

########################################
#             NOTES FILE
#
# THIS FILE IS AUTOMATICALLY GENERATED
#        DO NOT MODIFY THIS FILE!
########################################
info {
    created=1552596653
    version=4.4.3
    last_update_check=1552554585
    update_available=0
    last_version=4.4.3
    new_version=4.4.3
    }
programstatus {
    modified_host_attributes=0
    modified_service_attributes=0
    pid=11523
    daemon_mode=1
    program_start=1552593834
    last_log_rotation=0
    ...

Ideally, I would like to grab EACH segment (eg: "info", "programstatus", etc...) and add them to the JSON obj/array as I parse through it. With each attribute = value being assigned accordingly.

So something like:

$data = array();
// Loop here for each segment
$data['info'] = array(
    "created" => "1552596653",
    "version" => "4.4.3",
    etc...
)
// Then wrap it up with something like
return json_encode($data);

I just can't "think" to loop through the file while breaking it out into chunks.

I have the file contents via:

$statusFile = '/location/to/my/data/file';
ob_start();
include( $statusFile );
$statusFileContent = ob_get_contents();
ob_end_clean();
Answer 1

You need to accomplish 3 things:

  1. Load the file contents in a way that will allow you to read very large files without storing it entirely in memory.
  2. When getting each line, you need to run it through a parsing algorithm of your own design to be able to extract the data efficiently.
  3. You finally need to write each line's data to memory (or a file if you expect the data to be too large and might run out.

Here is a rough chunk of code I threw together that illustrates the approach you could take. I tested it on PHP Fiddle, but couldn't figure out how to share a link.

<?php
    // File path to load
    // $file = "/path/to/file.txt";
    $file = "https://pastebin.com/raw/gu2AC7qy";
    // Flag indicating we are inside of a "block"
    $inBlock = false;
    // Name/Key of current "block"
    $blockName = null;
    // Container for our data
    $data = [];
    // Open for reading
    $handle = fopen($file, 'r');
    // If we opened it (you should add better error handling)
    if ($handle) {
        // Grab each line one at a time
        while(($line = fgets($handle)) !== false) {
            // Cleanup line
            $line = trim($line);
            // Throw away useless lines (comments, empty, etc.)
            if (empty($line)) {
                // Skip blank lines
                continue;
            }
            if (substr($line, 1) == '#') {
                // Skip comments
                continue;
            }
            // Check if start of "block"
            if (substr($line, -1) == '{') {
                // Set the flag
                $inBlock = true;
                // Get the block name
                $blockName = trim(str_replace('{', '', $line));
                // Create new data section
                $data[$blockName] = [];
                // Get next line
                continue;
            }
            // If currently inside block
            if ($inBlock === true && ! empty($blockName)) {
                // Get a data attribute
                $dataRow = trim($line);
                // Parse as key/value
                $dataRowParts = explode("=", $dataRow);
                $key = isset($dataRowParts[0]) ? trim($dataRowParts[0]) : null;
                $value = isset($dataRowParts[1]) ? trim($dataRowParts[1]) : "";
                // Store in current block's data
                if ($key !== null) {
                    $data[$blockName][$key] = $value;
                }
                // Get next line
                continue;
            }
            // Check if end of "block"
            if (substr($line, -1) == '}') {
                // Clear flag
                $inBlock = false;
                // Unset block name
                $blockName = null;
                // Get next line 
                continue;
            }
        }
        // Close the file
        fclose($handle);
    }
    // Output data as JSON
    echo json_encode($data);
?>

Ideally you would put this logic in classes and methods so it's not a giant wall of code -- and of course add appropriate error handling. Good luck!

Answer 2

I made an elegant solution for you. You don't need loops, you can do it with 5 lines of code. Just use regex and transform the file you have.

$file = "Your file as a string";
//Get the titles like 'info' and put it around quotion marks
$titles_changed = preg_replace('/(.*)\{/', '"$1":{', $file, -1 );
//Get strings like created=1552596653 and transform to "created"="1552596653",
$values_changed = preg_replace('/(.*)=(.*)/', '"$1":"$2",', $titles_changed );
//Remove spaces from the string
$no_spaces = preg_replace('/\s/s', '', $values_changed);
//Fix all that became ",}" from the second replacement and transforms it into "},"
$limits_fixed = preg_replace('/\,\}/', '},', $no_spaces);
//Remove a "," that lasts on the end of the file and put all string around brakets
$json = "{". rtrim($limits_fixed, ',') . "}";
$object = json_decode($json);
Answer 3

You can take advantage of the fact that this is almost a .ini file.

Remove that top part and convert the bracketed groups into ini sections

$sections = preg_replace(['/#.*/', '/(\S+) \{/', '/}/'], ['', '[$1]', ''], $file_contents);

Then it's a .ini string.

$result = parse_ini_string($sections, true);
echo json_encode($result);
READ ALSO
PHP - How to Change Results from While Loop if Any Row Result Matches

PHP - How to Change Results from While Loop if Any Row Result Matches

I've looked for the result for this, and can't seem to find anything dealing with this specific issue

25
Apache2 + PHP-FPM - undefined function apache_getenv()

Apache2 + PHP-FPM - undefined function apache_getenv()

I have a big problem because for several hours I am trying to run a project that uses SetENV in PHPWhen he even tries to use a simple function apache_getenv();

38
How to definte variables for fields without data in them?

How to definte variables for fields without data in them?

I've got a number of calls to data in a WordPress site using a number of custom fieldsThe fields aren't required to fill out on the back end

16
laravel join 4 tables

laravel join 4 tables

I started to learn the Laravel 58 framework and got a problem

37