jean-pierre charras 9ede0ef25b CSV_WRITER(wxOutputStream& aStream) fix issue with non ASCII7 chars.
When writing non ASCII7 chars (using UTF8 encoding), the number of bytes to
write is bigger than the number of "chars", so the written lines were
truncated.
2025-05-05 15:55:55 +02:00

104 lines
2.5 KiB
C++

#include "csv.h"
#include <wx/txtstrm.h>
#include <rapidcsv/rapidcsv.h>
CSV_WRITER::CSV_WRITER( wxOutputStream& aStream ) :
m_stream( aStream ), m_delimiter( wxT( "," ) ),
m_quote( wxT( "\"" ) ), m_lineTerminator( wxT( "\n" ) ),
m_escape( wxEmptyString )
{
}
void CSV_WRITER::WriteLines( const std::vector<std::vector<wxString>>& aRows )
{
for( const auto& row : aRows )
{
WriteLine( row );
}
}
void CSV_WRITER::WriteLine( const std::vector<wxString>& cols )
{
wxString line;
for( size_t i = 0; i < cols.size(); ++i )
{
wxString colVal = cols[i];
if( i > 0 )
line += m_delimiter;
double test;
if( !colVal.ToDouble( &test ) )
{
bool useEscape = m_escape.size();
if( useEscape )
{
colVal.Replace( m_quote, m_escape + m_quote, true );
}
else
{
colVal.Replace( m_quote, m_quote + m_quote, true );
}
colVal = m_quote + colVal + m_quote;
}
line += colVal;
}
line += m_lineTerminator;
// Always write text on file using UTF8 encoding
std::string utf8str( line.utf8_string() );
m_stream.Write( utf8str.data(), utf8str.length() );
}
bool AutoDecodeCSV( const wxString& aInput, std::vector<std::vector<wxString>>& aData )
{
// Read the first line to determine the delimiter
bool trimCells = true;
bool skipCommentLines = true;
bool skipEmptyLines = true;
char commentPrefix = '#';
char delimiter = ',';
// Assume if we find a tab, we are dealing with a TSV file
if( aInput.find( '\t' ) != std::string::npos )
{
delimiter = '\t';
}
std::istringstream inputStream( aInput.ToStdString() );
rapidcsv::Document doc( inputStream, rapidcsv::LabelParams( -1, -1 ),
rapidcsv::SeparatorParams( delimiter, trimCells ), rapidcsv::ConverterParams(),
rapidcsv::LineReaderParams( skipCommentLines, commentPrefix, skipEmptyLines ) );
// Read the data into aData
aData.clear();
for( size_t i = 0; i < doc.GetRowCount(); ++i )
{
std::vector<wxString>& row = aData.emplace_back();
for( size_t j = 0; j < doc.GetColumnCount(); ++j )
{
std::string cell = doc.GetCell<std::string>( j, i );
row.emplace_back( cell );
}
}
// Anything in the first row?
return aData[0].size() > 0;
}