#include <GZCSVFileWriter.h>
Public Member Functions | |
| STANDARD_TYPEDEF (sella::file::GZCSVFileWriter) | |
| GZCSVFileWriter (const std::string &file, char delimiter=DefaultDelimiter, char seperator=DefaultSeperator) THROWS(IOException) | |
| virtual | ~GZCSVFileWriter () NO_EXCEPTIONS |
| void | write (const std::vector< std::string > &data) THROWS(IOException) |
| void | close (const std::string &rename=std::string()) THROWS(IOException) |
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 | |
| void | write (uint8_t *input, ssize_t length, int flush) THROWS(IOException) |
A GZIP compressed CSV writer.
Definition at line 31 of file GZCSVFileWriter.h.
| GZCSVFileWriter::GZCSVFileWriter | ( | const std::string & | file, | |
| char | delimiter = DefaultDelimiter, |
|||
| char | seperator = DefaultSeperator | |||
| ) |
The base constructor for a file writer.
| [in] | file | The name of the file to write. |
| [in] | delimiter | The field delimiter character for this file. |
| [in] | seperator | The record seperator character for this file. |
| IOException | if the file cannot be opened for writing. |
Definition at line 24 of file GZCSVFileWriter.cpp.
00024 : 00025 filename(file), 00026 00027 delimiter(delimiter), 00028 seperator(seperator), 00029 00030 descriptor(::open(file.c_str(), O_WRONLY | O_LARGEFILE | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) 00031 { 00032 /* Ensure the file was opened for writing, and zero all buffers and state machines. */ 00033 if (this->descriptor <= 0) { 00034 THROW(IOException, "failed to open file '%s' for writing", this->filename.c_str()); 00035 } 00036 memset(&(this->stream), 0, sizeof(this->stream)); 00037 memset(&(this->buffer), 0, sizeof(this->buffer)); 00038 00039 /* Initialize for the writing of GZIP compressed files. */ 00040 if (::deflateInit2(&(this->stream), 9 /* Best Compression */, Z_DEFLATED, 16 + MAX_WBITS /* GZIP */, 9 /* Maximum Memory and Speed */, Z_DEFAULT_STRATEGY) != Z_OK) { 00041 ::close(this->descriptor); 00042 00043 THROW(IOException, "failed to initilize zlib instance for writing file '%s'", this->filename.c_str()); 00044 } 00045 }
| GZCSVFileWriter::~GZCSVFileWriter | ( | ) | [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 51 of file GZCSVFileWriter.cpp.
References close().
00051 { 00052 if (this->descriptor != 0) { 00053 ::deflateEnd(&(this->stream)); 00054 00055 this->close(); 00056 } 00057 }
| void GZCSVFileWriter::close | ( | const std::string & | rename = std::string() |
) |
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] | rename | When set to a non-zero length string, the file will be renamed to the value in rename after closing. |
Definition at line 163 of file GZCSVFileWriter.cpp.
Referenced by ~GZCSVFileWriter().
00163 { 00164 uint8_t buffer[4]; 00165 00166 /* Close the compression stream out. */ 00167 this->write(buffer, 0, Z_FINISH); 00168 00169 ::close(this->descriptor); 00170 00171 if (rename.length() > 0) { 00172 ::rename(this->filename.c_str(), rename.c_str()); 00173 } 00174 this->filename.clear(); 00175 this->descriptor = 0; 00176 }
| void GZCSVFileWriter::write | ( | uint8_t * | input, | |
| ssize_t | length, | |||
| int | flush | |||
| ) | [protected] |
Append a character sequence to the file after compressing it.
| [in] | data | The bytes to compress before writing. |
| [in] | size | The number of bytes to compress. |
| [in] | flush | The zlib flush flag to utilize for the compression. |
| IOException | if unabled to write the supplied bytes for any reason. |
Definition at line 122 of file GZCSVFileWriter.cpp.
00122 { 00123 ssize_t expect; 00124 00125 this->stream.next_in = input; 00126 this->stream.avail_in = length; 00127 00128 do { 00129 this->stream.next_out = this->buffer[0]; 00130 this->stream.avail_out = sizeof(this->buffer[0]); 00131 00132 /* Compress the supplied data into the buffer. */ 00133 switch (::deflate(&(this->stream), flush)) { 00134 case Z_STREAM_ERROR: 00135 THROW(IOException, "zlib compression failure when writing buffer to compressed file '%s'", this->filename.c_str()); 00136 } 00137 00138 /* Write the compressed data to the file. */ 00139 if ((expect = (sizeof(this->buffer[0]) - this->stream.avail_out)) > 0) { 00140 while ((length = ::write(this->descriptor, this->buffer[0], sizeof(this->buffer[0]) - this->stream.avail_out)) != expect) { 00141 if (length == -1) { 00142 THROW(IOException, "failure writing buffer to compressed file '%s'", this->filename.c_str()); 00143 } 00144 expect -= length; 00145 } 00146 } 00147 } while (this->stream.avail_out == 0); 00148 00149 /* Ensure all data was compressed and written to the file. */ 00150 if (this->stream.avail_in != 0) { 00151 THROW(IOException, "failed to write full buffer to compressed file '%s'", this->filename.c_str()); 00152 } 00153 }
| void GZCSVFileWriter::write | ( | const std::vector< std::string > & | data | ) |
Append the next record to the file.
| [in] | data | The vector which contains all fields of the record. |
| IOException | if unabled to write the next record for any reason. |
Definition at line 66 of file GZCSVFileWriter.cpp.
00066 { 00067 size_t length = 0; 00068 00069 /* Write all fields, one at a time, to the compression stream. */ 00070 for (auto iter = data.begin(); iter != data.end(); ++iter) { 00071 ssize_t offset = 0; 00072 00073 /* Append the field delimiter if this is not the first field of the record. */ 00074 if (iter != data.begin()) { 00075 /* Purge the buffer if required to make room for the field delimiter. */ 00076 if (sizeof(this->delimiter) > (sizeof(this->buffer[1]) - length)) { 00077 this->write(this->buffer[1], length, Z_NO_FLUSH); 00078 00079 length = 0; 00080 } 00081 this->buffer[1][length++] = this->delimiter; 00082 } 00083 00084 do { /* Append the field value to the buffer. */ 00085 /* Copy as much of the field value as possible to the buffer. */ 00086 if ((iter->length() - offset) > (sizeof(this->buffer[1]) - length)) { 00087 ::memcpy(&(this->buffer[1][length]), &(iter->c_str()[offset]), sizeof(this->buffer[1]) - length); 00088 00089 this->write(this->buffer[1], sizeof(this->buffer[1]), Z_NO_FLUSH); 00090 00091 offset += (sizeof(this->buffer[1]) - length); 00092 length = 0; 00093 } else { 00094 ::memcpy(&(this->buffer[1][length]), &(iter->c_str()[offset]), iter->length() - offset); 00095 00096 length += (iter->length() - offset); 00097 offset += (iter->length() - offset); 00098 } 00099 } while (offset != static_cast<ssize_t>(iter->length())); 00100 } 00101 00102 /* Purge the buffer if required to make room for the record seperator. */ 00103 if (sizeof(this->seperator) > (sizeof(this->buffer[1]) - length)) { 00104 this->write(this->buffer[1], length, Z_NO_FLUSH); 00105 00106 length = 0; 00107 } 00108 this->buffer[1][length++] = this->seperator; 00109 00110 this->write(this->buffer[1], length, Z_NO_FLUSH); 00111 }
1.6.1