1 /*=========================================================================
2
3 Program: ParaView
4 Module: vtkDelimitedTextWriter.cxx
5
6 Copyright (c) Kitware, Inc.
7 All rights reserved.
8 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 /*-------------------------------------------------------------------------
16 Copyright 2009 Sandia Corporation.
17 Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
18 the U.S. Government retains certain rights in this software.
19 -------------------------------------------------------------------------*/
20
21 #include "vtkDelimitedTextWriter.h"
22
23 #include "vtkAlgorithm.h"
24 #include "vtkArrayIteratorIncludes.h"
25 #include "vtkCellData.h"
26 #include "vtkDataArray.h"
27 #include "vtkErrorCode.h"
28 #include "vtkInformation.h"
29 #include "vtkObjectFactory.h"
30 #include "vtkTable.h"
31 #include "vtkSmartPointer.h"
32
33 #include <vector>
34 #include <vtksys/ios/sstream>
35
36 vtkStandardNewMacro(vtkDelimitedTextWriter);
37 //-----------------------------------------------------------------------------
vtkDelimitedTextWriter()38 vtkDelimitedTextWriter::vtkDelimitedTextWriter()
39 {
40 this->StringDelimiter = 0;
41 this->FieldDelimiter = 0;
42 this->UseStringDelimiter = true;
43 this->SetStringDelimiter("\"");
44 this->SetFieldDelimiter(",");
45 this->Stream = 0;
46 this->FileName = 0;
47 this->WriteToOutputString = false;
48 this->OutputString = 0;
49 }
50
51 //-----------------------------------------------------------------------------
~vtkDelimitedTextWriter()52 vtkDelimitedTextWriter::~vtkDelimitedTextWriter()
53 {
54 this->SetStringDelimiter(0);
55 this->SetFieldDelimiter(0);
56 this->SetFileName(0);
57 delete this->Stream;
58 delete[] this->OutputString;
59 }
60
61 //-----------------------------------------------------------------------------
FillInputPortInformation(int vtkNotUsed (port),vtkInformation * info)62 int vtkDelimitedTextWriter::FillInputPortInformation(
63 int vtkNotUsed(port), vtkInformation* info)
64 {
65 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable");
66 return 1;
67 }
68
69 //-----------------------------------------------------------------------------
OpenStream()70 bool vtkDelimitedTextWriter::OpenStream()
71 {
72 if (this->WriteToOutputString)
73 {
74 this->Stream = new vtksys_ios::ostringstream;
75 }
76 else
77 {
78 if ( !this->FileName )
79 {
80 vtkErrorMacro(<< "No FileName specified! Can't write!");
81 this->SetErrorCode(vtkErrorCode::NoFileNameError);
82 return false;
83 }
84
85 vtkDebugMacro(<<"Opening file for writing...");
86
87 ofstream *fptr = new ofstream(this->FileName, ios::out);
88
89 if (fptr->fail())
90 {
91 vtkErrorMacro(<< "Unable to open file: "<< this->FileName);
92 this->SetErrorCode(vtkErrorCode::CannotOpenFileError);
93 delete fptr;
94 return false;
95 }
96
97 this->Stream = fptr;
98 }
99
100 return true;
101 }
102
103 //-----------------------------------------------------------------------------
104 template <class iterT>
vtkDelimitedTextWriterGetDataString(iterT * iter,vtkIdType tupleIndex,ostream * stream,vtkDelimitedTextWriter * writer,bool * first)105 void vtkDelimitedTextWriterGetDataString(
106 iterT* iter, vtkIdType tupleIndex, ostream* stream, vtkDelimitedTextWriter* writer,
107 bool* first)
108 {
109 int numComps = iter->GetNumberOfComponents();
110 vtkIdType index = tupleIndex* numComps;
111 for (int cc=0; cc < numComps; cc++)
112 {
113 if ((index+cc) < iter->GetNumberOfValues())
114 {
115 if (*first == false)
116 {
117 (*stream) << writer->GetFieldDelimiter();
118 }
119 *first = false;
120 (*stream) << iter->GetValue(index+cc);
121 }
122 else
123 {
124 if (*first == false)
125 {
126 (*stream) << writer->GetFieldDelimiter();
127 }
128 *first = false;
129 }
130 }
131 }
132
133 //-----------------------------------------------------------------------------
134 VTK_TEMPLATE_SPECIALIZE
vtkDelimitedTextWriterGetDataString(vtkArrayIteratorTemplate<vtkStdString> * iter,vtkIdType tupleIndex,ostream * stream,vtkDelimitedTextWriter * writer,bool * first)135 void vtkDelimitedTextWriterGetDataString(
136 vtkArrayIteratorTemplate<vtkStdString>* iter, vtkIdType tupleIndex,
137 ostream* stream, vtkDelimitedTextWriter* writer, bool* first)
138 {
139 int numComps = iter->GetNumberOfComponents();
140 vtkIdType index = tupleIndex* numComps;
141 for (int cc=0; cc < numComps; cc++)
142 {
143 if ((index+cc) < iter->GetNumberOfValues())
144 {
145 if (*first == false)
146 {
147 (*stream) << writer->GetFieldDelimiter();
148 }
149 *first = false;
150 (*stream) << writer->GetString(iter->GetValue(index+cc));
151 }
152 else
153 {
154 if (*first == false)
155 {
156 (*stream) << writer->GetFieldDelimiter();
157 }
158 *first = false;
159 }
160 }
161 }
162
163 //-----------------------------------------------------------------------------
GetString(vtkStdString string)164 vtkStdString vtkDelimitedTextWriter::GetString(vtkStdString string)
165 {
166 if (this->UseStringDelimiter && this->StringDelimiter)
167 {
168 vtkStdString temp = this->StringDelimiter;
169 temp += string + this->StringDelimiter;
170 return temp;
171 }
172 return string;
173 }
174
175 //-----------------------------------------------------------------------------
WriteData()176 void vtkDelimitedTextWriter::WriteData()
177 {
178 vtkTable* rg = vtkTable::SafeDownCast(this->GetInput());
179 if (rg)
180 {
181 this->WriteTable(rg);
182 }
183 else
184 {
185 vtkErrorMacro(<< "CSVWriter can only write vtkTable.");
186 }
187 }
188
189 //-----------------------------------------------------------------------------
WriteTable(vtkTable * table)190 void vtkDelimitedTextWriter::WriteTable(vtkTable* table)
191 {
192 vtkIdType numRows = table->GetNumberOfRows();
193 vtkDataSetAttributes* dsa = table->GetRowData();
194 if (!this->OpenStream())
195 {
196 return;
197 }
198
199 std::vector<vtkSmartPointer<vtkArrayIterator> > columnsIters;
200
201 int cc;
202 int numArrays = dsa->GetNumberOfArrays();
203 bool first = true;
204 // Write headers:
205 for (cc=0; cc < numArrays; cc++)
206 {
207 vtkAbstractArray* array = dsa->GetAbstractArray(cc);
208 for (int comp=0; comp < array->GetNumberOfComponents(); comp++)
209 {
210 if (!first)
211 {
212 (*this->Stream) << this->FieldDelimiter;
213 }
214 first = false;
215
216 vtksys_ios::ostringstream array_name;
217 array_name << array->GetName();
218 if (array->GetNumberOfComponents() > 1)
219 {
220 array_name << ":" << comp;
221 }
222 (*this->Stream) << this->GetString(array_name.str());
223 }
224 vtkArrayIterator* iter = array->NewIterator();
225 columnsIters.push_back(iter);
226 iter->Delete();
227 }
228 (*this->Stream) << "\n";
229
230 for (vtkIdType index=0; index < numRows; index++)
231 {
232 first = true;
233 std::vector<vtkSmartPointer<vtkArrayIterator> >::iterator iter;
234 for (iter = columnsIters.begin(); iter != columnsIters.end(); ++iter)
235 {
236 switch ((*iter)->GetDataType())
237 {
238 vtkArrayIteratorTemplateMacro(
239 vtkDelimitedTextWriterGetDataString(static_cast<VTK_TT*>(iter->GetPointer()),
240 index, this->Stream, this, &first));
241 case VTK_VARIANT:
242 {
243 vtkDelimitedTextWriterGetDataString(static_cast<vtkArrayIteratorTemplate<vtkVariant>*>(iter->GetPointer()),
244 index, this->Stream, this, &first);
245 break;
246 }
247 }
248 }
249 (*this->Stream) << "\n";
250 }
251
252 if (this->WriteToOutputString)
253 {
254 vtksys_ios::ostringstream *ostr =
255 static_cast<vtksys_ios::ostringstream*>(this->Stream);
256
257 delete [] this->OutputString;
258 size_t strLen = ostr->str().size();
259 this->OutputString = new char[strLen+1];
260 memcpy(this->OutputString, ostr->str().c_str(), strLen+1);
261 }
262 delete this->Stream;
263 this->Stream = 0;
264 }
265
266 //-----------------------------------------------------------------------------
RegisterAndGetOutputString()267 char *vtkDelimitedTextWriter::RegisterAndGetOutputString()
268 {
269 char *tmp = this->OutputString;
270 this->OutputString = NULL;
271
272 return tmp;
273 }
274
275 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)276 void vtkDelimitedTextWriter::PrintSelf(ostream& os, vtkIndent indent)
277 {
278 this->Superclass::PrintSelf(os, indent);
279 os << indent << "FieldDelimiter: " << (this->FieldDelimiter ?
280 this->FieldDelimiter : "(none)") << endl;
281 os << indent << "StringDelimiter: " << (this->StringDelimiter ?
282 this->StringDelimiter : "(none)") << endl;
283 os << indent << "UseStringDelimiter: " << this->UseStringDelimiter << endl;
284 os << indent << "FileName: " << (this->FileName? this->FileName : "none")
285 << endl;
286 os << indent << "WriteToOutputString: " << this->WriteToOutputString << endl;
287 }
288