├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── example ├── example.dat └── parsing.php └── library └── Fanatique └── Parser ├── FixedLengthFileParser.php ├── ParserException.php └── ParserInterface.php /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_STORE 2 | INSTALL.txt 3 | LICENSE.txt 4 | README.txt 5 | demos/ 6 | extras/documentation 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License (http://opensource.org/licenses/MIT) 2 | 3 | Copyright (c) 2014 Alexander Thomas (me@alexander-thomas.net) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 12 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 13 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 14 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 15 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | php-fixed-length-file-parser 2 | ============================ 3 | 4 | A parser class for handling fixed length text files in PHP. 5 | 6 | Fixed Length Files (aka poor man's CSV) are plain text files with one data set per row 7 | _but without any delimiter_. 8 | 9 | 01Amy BLUES 10 | 02Bob REDS 11 | ... 12 | 13 | ## Features ## 14 | 15 | This class provides a rather comfortable way to handle this type of file on PHP. 16 | 17 | You can: 18 | 19 | - register a pre flight check to determine whether or not a row has to be parsed 20 | - register a callback to handle each line 21 | - register a chopping map which transforms each row into an assiciative array 22 | 23 | 24 | ## Usage ## 25 | 26 | The following example shows how to transform a fixed length file into an associative array. 27 | The working example can be found in `example/parsing.php`. 28 | 29 | $parser = new \Fanatique\Parser\FixedLengthFileParser(); 30 | 31 | //Set the chopping map (aka where to extract the fields) 32 | $parser->setChoppingMap(array( 33 | array('field_name' => 'id', 'start' => 0, 'length' => 2), 34 | array('field_name' => 'name', 'start' => 2, 'length' => 5), 35 | array('field_name' => 'team', 'start' => 7, 'length' => 5), 36 | )); 37 | 38 | ``field_name`` and ``length`` are required and ``start`` is an optional parameter. If ``start`` is omitted, it will be set to the ``start`` plus ``length`` value of the previous map entry. 39 | 40 | //Set the absolute path to the file 41 | $parser->setFilePath(__DIR__ . '/example.dat'); 42 | 43 | //Parse the file 44 | try { 45 | $parser->parse(); 46 | } catch (\Fanatique\Parser\ParserException $e) { 47 | echo 'ERROR - ' . $e->getMessage() . PHP_EOL; 48 | exit(1); 49 | } 50 | 51 | //Get the content 52 | var_dump($parser->getContent()); 53 | 54 | ### Registering a pre flight check ### 55 | 56 | A pre flight check can be registered to be applied to each row *before* it is parsed. 57 | The closure needs to return a boolean value with: 58 | 59 | - `false`: line needs not to be parsed 60 | - `true`: parse line 61 | 62 | This example ignores any line which md5 sum is `f23f81318ef24f1ba4df4781d79b7849`: 63 | 64 | $linesToIgnore = array('f23f81318ef24f1ba4df4781d79b7849'); 65 | $parser->setPreflightCheck(function($currentLineStr) use($linesToIgnore) { 66 | if (in_array(md5($currentLineStr), $linesToIgnore)) { 67 | //Ignore line 68 | $ret = false; 69 | } else { 70 | //Parse line 71 | $ret = true; 72 | } 73 | return $ret; 74 | } 75 | ); 76 | 77 | ### Registering a callback ### 78 | 79 | Finally you can register a callback which is applied to each parsed line and allows you to process it. 80 | The closure gets the parsed line as an array and it is expected to return an array of the same format. 81 | 82 | $parser->setCallback(function(array $currentLine) { 83 | $currentLine['team'] = ucwords(strtolower($currentLine['team'])); 84 | return $currentLine; 85 | } 86 | ); 87 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fanatique/php-fixed-length-file-parser", 3 | "description": "A parser class for handling fixed length text files in PHP", 4 | "keywords": ["php", "text", "parser", "fixed length"], 5 | "homepage": "https://github.com/fanatique/php-fixed-length-file-parser", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Alexander Thomas", 10 | "email": "me@alexander-thomas.net", 11 | "homepage": "http://alexander-thomas.net" 12 | } 13 | ], 14 | "autoload": { 15 | "psr-0": { 16 | "Fanatique": "library/" 17 | } 18 | }, 19 | "version": "dev-master", 20 | "require": { 21 | "php": ">=5.3.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/example.dat: -------------------------------------------------------------------------------- 1 | 01Amy BLUES 2 | 02Bob REDS 3 | 03ChuckBLUES 4 | 04Dick BLUES 5 | 05EthelREDS 6 | 06Fred BLUES 7 | 07GillyBLUES 8 | 08Hank REDS 9 | -------------------------------------------------------------------------------- /example/parsing.php: -------------------------------------------------------------------------------- 1 | setChoppingMap(array( 22 | array('field_name' => 'id', 'length' => 2), 23 | array('field_name' => 'name', 'start'=>2, 'length' => 5), 24 | array('field_name' => 'team', 'length' => 5), // start is the sum of name:start(2) plus name:length(5) = 7 25 | )); 26 | 27 | //Set the absolute path to the file 28 | $parser->setFilePath(__DIR__ . '/example.dat'); 29 | 30 | //## 1a. optional features 31 | //Register a closure that determines if a line needs to be parsed 32 | //This example ignores any line which md5 sum is f23f81318ef24f1ba4df4781d79b7849 (which kicks out Gilly) 33 | $linesToIgnore = array('f23f81318ef24f1ba4df4781d79b7849'); 34 | $parser->setPreflightCheck(function($currentLineStr) use($linesToIgnore) { 35 | if (in_array(md5($currentLineStr), $linesToIgnore)) { 36 | //Ignore line 37 | $ret = false; 38 | } else { 39 | //Parse line 40 | $ret = true; 41 | } 42 | return $ret; 43 | } 44 | ); 45 | 46 | 47 | //Register a callback which is applied to each parsed line 48 | $parser->setCallback(function(array $currentLine) { 49 | $currentLine['team'] = ucwords(strtolower($currentLine['team'])); 50 | return $currentLine; 51 | } 52 | ); 53 | 54 | //## 2. Parse 55 | try { 56 | $parser->parse(); 57 | } catch (\Fanatique\Parser\ParserException $e) { 58 | echo 'ERROR - ' . $e->getMessage() . PHP_EOL; 59 | exit(1); 60 | } 61 | 62 | //## 3. Get the content 63 | 64 | var_dump($parser->getContent()); 65 | -------------------------------------------------------------------------------- /library/Fanatique/Parser/FixedLengthFileParser.php: -------------------------------------------------------------------------------- 1 | array( 62 | * array('field_name' => 'id,' 'start' => 0, 'length' => 2), 63 | * ... 64 | * ) 65 | * 66 | * @param array $map 67 | */ 68 | public function setChoppingMap(array $map) 69 | { 70 | $this->choppingMap = $map; 71 | } 72 | 73 | /** 74 | * Setter for the file to be parsed 75 | * @param string $pathToFile /path/to/file.dat 76 | */ 77 | public function setFilePath($pathToFile) 78 | { 79 | $this->file = (string) $pathToFile; 80 | } 81 | 82 | /** 83 | * Setter for registering a closure that 84 | * evaluates if a fetched line needs to be parsed. 85 | * 86 | * The closure needs to 87 | *