#include <GZCSVFileReader.h>
Public Member Functions | |
| STANDARD_TYPEDEF (sella::file::GZCSVFileReader) | |
| GZCSVFileReader (const std::string &file, char delimiter=DefaultDelimiter, char seperator=DefaultSeperator) THROWS(IOException) | |
| virtual | ~GZCSVFileReader () NO_EXCEPTIONS |
| void | read (std::vector< std::vector< std::string >> &data) THROWS(IOException) |
| void | close (bool unlink=false) NO_EXCEPTIONS |
Static Public Attributes | |
| static const char | DefaultDelimiter = 0x1e |
| The default delimiter used between the fields of a record; the ASCII record seperator character. | |
| static const char | DefaultSeperator = 0x1d |
| The default seperator used between the records of a file; the ASCII group seperator character. | |
Protected Member Functions | |
| bool | read (std::vector< std::string > &data, std::string prepend) THROWS(IOException) |
| bool | read (std::vector< std::string > &data) THROWS(IOException) |
A GZIP compressed CSV reader.
Definition at line 31 of file GZCSVFileReader.h.
| GZCSVFileReader::GZCSVFileReader | ( | const std::string & | file, | |
| char | delimiter = DefaultDelimiter, |
|||
| char | seperator = DefaultSeperator | |||
| ) |
The base constructor for a file reader.
| [in] | file | The name of the database file to read. |
| IOException | if the file cannot be opened for reading. |
Definition at line 22 of file GZCSVFileReader.cpp.
00022 : 00023 filename(file), 00024 00025 delimiter(delimiter), 00026 seperator(seperator), 00027 00028 descriptor(::open(file.c_str(), O_RDONLY | O_LARGEFILE)) 00029 { 00030 /* Ensure the file was opened for reading, and zero all buffers and state machines. */ 00031 if (this->descriptor <= 0) { 00032 THROW(IOException, "failed to open file '%s' for reading", this->filename.c_str()); 00033 } 00034 memset(&(this->stream), 0, sizeof(this->stream)); 00035 memset(&(this->buffer), 0, sizeof(this->buffer)); 00036 00037 /* Initialize for the reading of GZIP compressed files. */ 00038 if (::inflateInit2(&(this->stream), 16 + MAX_WBITS) != Z_OK) { 00039 ::close(this->descriptor); 00040 00041 THROW(IOException, "failed to initilize zlib instance for reading file '%s'", this->filename.c_str()); 00042 } 00043 this->stream.avail_out = sizeof(this->buffer[1]); 00044 }
| GZCSVFileReader::~GZCSVFileReader | ( | ) | [virtual] |
The class destructor; this destructor closes the file opened by this instance if it was not explicitly closed by the class user.
Definition at line 50 of file GZCSVFileReader.cpp.
References close().
00050 { 00051 if (this->descriptor != 0) { 00052 ::inflateEnd(&(this->stream)); 00053 00054 this->close(); 00055 } 00056 }
| void GZCSVFileReader::close | ( | bool | unlink = false |
) |
Close the file opened by this instance. Failure to explicitly call this function will not cause a file descriptor leak if the class destructor is called: the destructor will call close() automatically if necessary.
| [in] | unlink | When set to true, the file will be unlinked on close. |
Definition at line 104 of file GZCSVFileReader.cpp.
Referenced by sella::file::GZCSVPathReader::read(), and ~GZCSVFileReader().
00104 { 00105 ::close(this->descriptor); 00106 00107 if (unlink == true) { 00108 ::unlink(this->filename.c_str()); 00109 } 00110 this->filename.clear(); 00111 this->descriptor = 0; 00112 }
| bool GZCSVFileReader::read | ( | std::vector< std::string > & | data | ) | [protected] |
Read the next record from the file and return all fields.
| [out] | data | The vector in which to store all fields from the returned record. |
| IOException | if unabled to read the next record for any reason. |
Definition at line 89 of file GZCSVFileReader.cpp.
00089 { 00090 /* Read field entries from the memory buffer, and as necessary fall back to reading from the disk. */ 00091 while (this->read(data, std::string()) == false) { 00092 /* EMPTY LOOP */ 00093 } 00094 return data.empty() ? false : true; 00095 }
| bool GZCSVFileReader::read | ( | std::vector< std::string > & | data, | |
| std::string | prepend | |||
| ) | [protected] |
Read the next field from the file. If required, this function will obtain additional data from the file and/or decompress additional data from the compressed data buffer.
| [out] | data | The vector in which to store all fields from the returned record; if not empty when called, the function will clear the vector before writing the next set of fields to it. |
| [in] | prepend | A text value to prepend the the next field value; this is used for recursive calls on long or broken up (due to buffer size) fields. |
| IOException | if unabled to read the next field for any reason. |
Definition at line 131 of file GZCSVFileReader.cpp.
00131 { 00132 uint8_t * head = this->stream.next_out - (sizeof(this->buffer[1]) - this->stream.avail_out); 00133 00134 /* Determine if there is decopmressed data available. */ 00135 if (this->stream.avail_out == sizeof(this->buffer[1])) { 00136 /* There is no decopressed data available, so determine if there is compressed data available in memory. */ 00137 if (this->stream.avail_in == 0) { 00138 /* There is no compressed data available, so read data from file into the compressed data buffer. */ 00139 if ((this->stream.avail_in = ::read(this->descriptor, this->buffer[0], sizeof(this->buffer[0]))) < 0) { 00140 THROW(IOException, "failed to read from file '%s'", this->filename.c_str()); 00141 } else if (this->stream.avail_in == 0) { 00142 return true; /* The end of the file was reached, and no more data could be read. */ 00143 } 00144 this->stream.next_in = this->buffer[0]; 00145 } 00146 00147 /* Decompress data from the compressed buffer into the uncompressed buffer. */ 00148 this->stream.avail_out = sizeof(this->buffer[1]); 00149 this->stream.next_out = this->buffer[1]; 00150 00151 switch (::inflate(&(this->stream), Z_SYNC_FLUSH)) { 00152 case Z_STREAM_ERROR: 00153 THROW(IOException, "zlib decompression state was destroyed"); 00154 00155 case Z_NEED_DICT: 00156 THROW(IOException, "zlib decompression failed due to missing dictionary"); 00157 00158 case Z_DATA_ERROR: 00159 THROW(IOException, "zlib decompression failed due to bad data in stream"); 00160 00161 case Z_MEM_ERROR: 00162 THROW(IOException, "zlib decompression failed due to a memory error"); 00163 } 00164 head = this->stream.next_out - (sizeof(this->buffer[1]) - this->stream.avail_out); 00165 } 00166 00167 /* Adjust the limits of the decompressed memory buffer. */ 00168 for (uint8_t * i = head; i != this->stream.next_out; i++) { 00169 if ((*i) == this->seperator) { /* The end of the record has been reached; store the last field and return success. */ 00170 data.push_back(prepend.append(std::string(reinterpret_cast<char *>(head), i - head))); 00171 this->stream.avail_out += (i - head + 1); 00172 00173 return true; /* The record request has been fullfilled. */ 00174 } else if (*(i) == this->delimiter) { /* A record delimiter has been identified. */ 00175 data.push_back(prepend.append(std::string(reinterpret_cast<char *>(head), i - head))); 00176 this->stream.avail_out += (i - head + 1); 00177 00178 return false; /* The record request has not yet been fullfilled. */ 00179 } 00180 } 00181 this->stream.avail_out = sizeof(this->buffer[1]); 00182 00183 /* Recursively call this function with a prepend value supplied to account for a field which is too long for the buffers. */ 00184 return this->read(data, std::string(reinterpret_cast<char *>(head), this->stream.next_out - head)); 00185 }
| void GZCSVFileReader::read | ( | std::vector< std::vector< std::string >> & | data | ) |
Read the all fields from the file.
| [out] | data | The vector in which to store all data from the file. |
| IOException | if unabled to read the file for any reason. |
Definition at line 65 of file GZCSVFileReader.cpp.
Referenced by sella::file::GZCSVPathReader::read().
00065 { 00066 do { 00067 if ((data.empty() == false) && data.back().empty()) { 00068 data.pop_back(); 00069 } 00070 data.push_back(std::vector<std::string>()); 00071 } while (this->read(data.back()) == true); 00072 00073 if ((data.empty() == false) && data.back().empty()) { 00074 data.pop_back(); 00075 } 00076 }
1.6.1