3 * An universal class for file input/output streams.
5 class FileIOStream extends BaseFrameworkSystem implements FileInputStreamer, FileOutputStreamer {
9 private function __construct () {
10 // Call parent constructor
11 parent::constructor(__CLASS__);
13 // Set part description
14 $this->setPartDescr("Universal Datei-Ein-/Ausgabesystem");
17 $this->createUniqueID();
20 $this->removeNumberFormaters();
21 $this->removeSystemArray();
25 * Create a file IO stream. This is a class for performing all actions
26 * on files like creating, deleting and loading them.
28 * @return $ioInstance An instance of FileIOStream
30 public final static function createFileIOStream () {
31 // Create new instance
32 $ioInstance = new FileIOStream();
34 // Return the instance
39 * Saves data to a given local file
41 * @param $fileName The file name for the to be saved file
42 * @param $dataArray The data we shall store to the file
44 * @see FileOutputStreamer
46 public final function saveFile ($fileName, $dataArray) {
48 $dirName = ""; $fileInstance = null;
49 for ($idx = 0; $idx < 5; $idx++) {
50 // Get a file output pointer
52 $fileInstance = FrameworkFileOutputPointer::createFrameworkFileOutputPointer($fileName, 'w');
53 } catch (FilePointerNotOpenedException $e) {
54 // Create missing directory
55 $dirName = dirname($fileName);
56 for ($idx2 = 0; $idx2 < (2 - $idx); $idx2++) {
57 $dirName = dirname($dirName);
64 // Write a header information for validation purposes
65 $fileInstance->writeToFile(sprintf("@head^%s:%s:%s:%s\n",
68 strlen($dataArray[1]),
72 // Encode the (maybe) binary stream with Base64
73 $b64Stream = base64_encode($dataArray[1]);
75 // write the data line by line
76 $line = str_repeat(" ", 50); $idx = 0;
77 while (strlen($line) == 50) {
78 // Get 50 chars or less
79 $line = substr($b64Stream, $idx, 50);
81 // Save it to the stream
82 $fileInstance->writeToFile(sprintf("@data^%s:%s\n",
87 // Advance to the next 50-chars block
92 $fileInstance->closeFile();
96 * Reads from a local file
98 * @param $fqfn The full-qualified file-name which we shall load
99 * @return $array An array with the element 'header' and 'data'
100 * @see FileInputStreamer
102 public final function loadFileContents ($fqfn) {
103 // Initialize some variables and arrays
108 $readData = ""; // This will contain our read data
110 // Get a file input handler
111 $fileInstance = FrameworkFileInputPointer::createFrameworkFileInputPointer($fqfn);
113 // Read all it's contents (we very and transparently decompress it below)
114 while ($readRawLine = $fileInstance->readFromFile()) {
115 // Add the read line to the buffer
116 $inputBuffer .= $readRawLine;
118 // Break infinite loop maybe caused by the input handler
119 if ($lastBuffer == $inputBuffer) break;
121 // Remember last read line for avoiding possible infinite loops
122 $lastBuffer = $inputBuffer;
125 // Close directory handle
126 $fileInstance->closeFile();
128 // Convert it into an array
129 $inputBuffer = explode("\n", $inputBuffer);
131 // Now process the read lines and verify it's content
132 foreach ($inputBuffer as $rawLine) {
133 // Trim it a little but not the leading spaces/tab-stops
134 $rawLine = rtrim($rawLine);
137 if (substr($rawLine, 0, 5) == "@head") {
138 // Header found, so let's extract it
139 $header = explode("^", $rawLine);
140 $header = trim($header[1]);
142 // Now we must convert it again into an array
143 $header = explode(":", $header);
145 // Is the header (maybe) valid?
146 if (count($header) != 4) {
147 // Throw an exception
148 throw new InvalidArrayCountException(array($this, "header", count($header), 4), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
150 } elseif (substr($rawLine, 0, 5) == "@data") {
152 $data = explode("^", $rawLine);
155 // First element is the data, second the MD5 checksum
156 $data = explode(":", $data);
158 // Validate the read line
159 if (count($data) == 2) {
160 if (md5($data[0]) != $data[1]) {
161 // MD5 hash did not match!
162 throw new InvalidMD5ChecksumException(array($this, md5($data[0]), $data[1]), self::EXCEPTION_MD5_CHECKSUMS_MISMATCH);
166 throw new InvalidArrayCountException(array($this, "data", count($data), 2), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
169 // Add this to the readData string
170 $readData .= $data[0];
172 // Other raw lines than header/data tagged lines and re-add the new-line char
173 $readData .= $rawLine."\n";
177 // Was raw lines read and no header/data?
178 if ((!empty($readData)) && (count($header) == 0) && (count($data) == 0)) {
179 // Return raw lines back
183 // Was a header found?
184 if (count($header) != 4) {
185 // Throw an exception
186 throw new InvalidArrayCountException(array($this, "header", count($header), 4), self::EXCEPTION_ARRAY_HAS_INVALID_COUNT);
189 // Decode all from Base64
190 $readData = @base64_decode($readData);
192 // Does the size match?
193 if (strlen($readData) != $header[2]) {
194 // Size did not match
195 throw new InvalidDataLengthException(array($this, strlen($readData), $header[2]), self::EXCEPTION_UNEXPECTED_STRING_SIZE);
198 // Validate the decoded data with the final MD5 hash
199 if (md5($readData) != $header[3]) {
200 // MD5 hash did not match!
201 throw new InvalidMD5ChecksumException(array($this, md5($readData), $header[3]), self::EXCEPTION_MD5_CHECKSUMS_MISMATCH);
204 // Return all in an array