]> git.mxchange.org Git - core.git/blob - framework/main/classes/file_directories/text/input/csv/class_CsvInputFile.php
Rewrite:
[core.git] / framework / main / classes / file_directories / text / input / csv / class_CsvInputFile.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Filesystem\Input\Csv;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Filesystem\Text\BaseInputTextFile;
7 use Org\Mxchange\CoreFramework\Stream\Filesystem\CsvInputStreamer;
8
9 // Import SPL stuff
10 use \SplFileInfo;
11
12 /**
13  * A CSV file input class for writing CSV files
14  *
15  * @author              Roland Haeder <webmaster@ship-simu.org>
16  * @version             0.0.0
17  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team
18  * @license             GNU GPL 3.0 or any newer version
19  * @link                http://www.ship-simu.org
20  *
21  * This program is free software: you can redistribute it and/or modify
22  * it under the terms of the GNU General Public License as published by
23  * the Free Software Foundation, either version 3 of the License, or
24  * (at your option) any later version.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License
32  * along with this program. If not, see <http://www.gnu.org/licenses/>.
33  */
34 class CsvInputFile extends BaseInputTextFile implements CsvInputStreamer {
35         /**
36          * Protected constructor
37          *
38          * @return      void
39          */
40         private function __construct () {
41                 // Call parent constructor
42                 parent::__construct(__CLASS__);
43         }
44
45         /**
46          * Creates an instance of this File class and prepares it for usage
47          *
48          * @param       $infoInstance   An instance of a SplFileInfo class
49          * @return      $fileInstance   An instance of this File class
50          */
51         public final static function createCsvInputFile (SplFileInfo $infoInstance) {
52                 // Get a new instance
53                 $fileInstance = new CsvInputFile();
54
55                 // Init this abstract file
56                 $fileInstance->initFile($infoInstance);
57
58                 // Return the prepared instance
59                 return $fileInstance;
60         }
61
62         /**
63          * Reads a line from CSV file and returns it as an indexed array. Please
64          * note that strings *must* be always in double-quotes, else any found
65          * column separators will be parsed or they may be interpreted incorrectly.
66          *
67          * @param       $columnSeparator        Character to use separting columns
68          * @return      $lineArray                      An indexed array with the read line
69          */
70         public function readCsvFileLine (string $columnSeparator) {
71                 // Read raw line
72                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] columnSeparator=%s - CALLED!', __METHOD__, __LINE__, $columnSeparator));
73                 $data = $this->getPointerInstance()->readLine();
74
75                 // Parse data
76                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] data()=%d', __METHOD__, __LINE__, strlen($data)));
77                 $lineArray = $this->parseDataToIndexedArray($data, $columnSeparator);
78
79                 // Return it
80                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] lineArray()=%d - EXIT!', __METHOD__, __LINE__, count($lineArray)));
81                 return $lineArray;
82         }
83
84         /**
85          * Parses given data into an array
86          *
87          * @param       $data                           Raw data e.g. returned from readLine()
88          * @param       $columnSeparator        Character to use separting columns
89          * @return      $lineArray                      An indexed array with the read line
90          */
91         private function parseDataToIndexedArray (string $data, string $columnSeparator) {
92                 // Init return array
93                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] data()=%d,columnSeparator=%s - CALLED!', __METHOD__, __LINE__, strlen($data), $columnSeparator));
94                 $lineArray = [];
95
96                 // Whether the parser reads a quoted string (which may contain the column separator again)
97                 $isInQuotes = false;
98
99                 // Init column data
100                 $column = '';
101
102                 // Now parse the line
103                 for ($idx = 0; $idx < strlen($data); $idx++) {
104                         // "Cache" char
105                         $char = substr($data, $idx, 1);
106
107                         // Is the column separator found and not within quotes?
108                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] idx=%d,char=%s ...', __METHOD__, __LINE__, $idx, $char));
109                         if (($isInQuotes === false) && ($char == $columnSeparator)) {
110                                 // Add this line to the array
111                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] Adding column=%s ...', __METHOD__, __LINE__, $column));
112                                 array_push($lineArray, $column);
113
114                                 // Clear variable ...
115                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] line[]=%d - After add!', __METHOD__, __LINE__, count($lineArray)));
116                                 $column = '';
117
118                                 // ... and skip it
119                                 continue;
120                         } elseif ($char == chr(34)) {
121                                 // $column must be empty at this point if we are at starting quote
122                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] column=%s ...', __METHOD__, __LINE__, $column));
123                                 assert(($isInQuotes === true) || (empty($column)));
124
125                                 // Double-quote found, so flip variable
126                                 $isInQuotes = (!$isInQuotes);
127
128                                 // Skip double-quote (escaping of them is not yet supported)
129                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] isInQuotes=%d ...', __METHOD__, __LINE__, intval($isInQuotes)));
130                                 continue;
131                         }
132
133                         // Add char to column
134                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] Adding char=%s ...', __METHOD__, __LINE__, $idx, $char));
135                         $column .= $char;
136                 }
137
138                 // Is there something outstanding?
139                 if (!empty($column)) {
140                         // Then don't forget this. :-)
141                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] Adding column=%s ...', __METHOD__, __LINE__, $column));
142                         array_push($lineArray, $column);
143
144                         // Debug message
145                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] line[]=%d - After add!', __METHOD__, __LINE__, count($lineArray)));
146                 }
147
148                 // Return it
149                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] line[]=%d - EXIT!', __METHOD__, __LINE__, count($lineArray)));
150                 return $lineArray;
151         }
152
153 }
154