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