reading read lumenworks framework example c# flat-file csv

lumenworks - read csv file c# example



escapando una cadena complicada al formato CSV (6)

Tengo que crear un archivo CSV a partir del resultado del servicio web y el archivo CSV utiliza cadenas entre comillas con el separador de comas. No puedo cambiar el formato ...

Entonces, si tengo una string se convierte en una "string" ... Si el valor ya tiene comillas, se sustituyen por comillas dobles. Por ejemplo, un str"ing convierte en "str""ing" ...

Sin embargo, últimamente mi importación ha estado fallando debido a lo siguiente

  • La cadena de entrada original es: "","word1,word2,..."
  • cada cita se reemplaza por doble, lo que da como resultado: """",""word1,word2,...""
  • luego se prefija y se le agrega el sufijo con la cita antes del archivo CVS: """"",""word1,word2,..."""

Como pueden ver, el resultado final es este:

""""",""word1,word2,..."""

que rompe mi importación (lo ve como otro campo) ... Creo que el problema es la aparición de "," en la cadena de entrada original.

¿Hay una secuencia de escape de CVS para este escenario?

Actualizar

La razón por la cual las rupturas anteriores se deben a un archivo de mapeo BCP (la utilidad BCP se usa para cargar archivos CSV en SQL db) que tiene un terminador definido como "," . Entonces, en lugar de ver 1 campo, ve 2 ... Pero no puedo cambiar el archivo de mapeo ...


Basado en la contribución de "Ed Bayiates", aquí hay una clase útil para construir un documento csv:

/// <summary> /// helpful class to build csv document /// </summary> public class CsvBuilder { /// <summary> /// create the csv builder /// </summary> public CsvBuilder(char csvSeparator) { m_csvSeparator = csvSeparator; } /// <summary> /// append a cell /// </summary> public void appendCell(string strCellValue) { if (m_nCurrentColumnIndex > 0) m_strBuilder.Append(m_csvSeparator); bool mustQuote = (strCellValue.Contains(m_csvSeparator) || strCellValue.Contains(''/"'') || strCellValue.Contains(''/r'') || strCellValue.Contains(''/n'')); if (mustQuote) { m_strBuilder.Append(''/"''); foreach (char nextChar in strCellValue) { m_strBuilder.Append(nextChar); if (nextChar == ''"'') m_strBuilder.Append(''/"''); } m_strBuilder.Append(''/"''); } else { m_strBuilder.Append(strCellValue); } m_nCurrentColumnIndex++; } /// <summary> /// end of line, new line /// </summary> public void appendNewLine() { m_strBuilder.Append(Environment.NewLine); m_nCurrentColumnIndex = 0; } /// <summary> /// Create the CSV file /// </summary> /// <param name="path"></param> public void save(string path ) { File.WriteAllText(path, ToString()); } public override string ToString() { return m_strBuilder.ToString(); } private StringBuilder m_strBuilder = new StringBuilder(); private char m_csvSeparator; private int m_nCurrentColumnIndex = 0; }

Cómo usarlo:

void exportAsCsv( string strFileName ) { CsvBuilder csvStringBuilder = new CsvBuilder('';''); csvStringBuilder.appendCell("#Header col 1 : Name"); csvStringBuilder.appendCell("col 2 : Value"); csvStringBuilder.appendNewLine(); foreach (Data data in m_dataSet) { csvStringBuilder.appendCell(data.getName()); csvStringBuilder.appendCell(data.getValue()); csvStringBuilder.appendNewLine(); } csvStringBuilder.save(strFileName); }


Basado en la respuesta de Ed Bayiates:

/// <summary> /// Turn a string into a CSV cell output /// </summary> /// <param name="value">String to output</param> /// <returns>The CSV cell formatted string</returns> private string ConvertToCsvCell(string value) { var mustQuote = value.Any(x => x == '','' || x == ''/"'' || x == ''/r'' || x == ''/n''); if (!mustQuote) { return value; } value = value.Replace("/"", "/"/""); return string.Format("/"{0}/"", value); }


Después de mucha deliberación, se decidió que era necesario arreglar el formato de la utilidad de importación. El escape de la cadena era correcto (como lo indicaron los usuarios), pero el archivo de formato que la herramienta de importación utilizaba era incorrecto y causaba que se interrumpiera la importación.

Gracias a todos y gracias especiales a @dbt (voto ascendente)


El primer paso para analizar esto es eliminar los "extra" añadidos alrededor de su cadena. Una vez que haga esto, debería ser capaz de tratar con los incrustados "así como también".


Mi penique pensó:

String[] lines = new String[] { "/"/",/"word/",word,word2,1,34,5,2,/"details/"" }; for (int j = 0; j < lines.Length; j++) { String[] fields=lines[j].Split('',''); for (int i =0; i<fields.Length; i++) { if (fields[i].StartsWith("/"") && fields[i].EndsWith("/"")) { char[] tmp = new char[fields[i].Length-2]; fields[i].CopyTo(1,tmp,0,fields[i].Length-2); fields[i] =tmp.ToString(); fields[i] = "/""+fields[i].Replace("/"","/"/"")+"/""; } else fields[i] = fields[i].Replace("/"","/"/""); } lines[j]=String.Join(",",fields);

}


Uso este código y siempre ha funcionado:

/// <summary> /// Turn a string into a CSV cell output /// </summary> /// <param name="str">String to output</param> /// <returns>The CSV cell formatted string</returns> public static string StringToCSVCell(string str) { bool mustQuote = (str.Contains(",") || str.Contains("/"") || str.Contains("/r") || str.Contains("/n")); if (mustQuote) { StringBuilder sb = new StringBuilder(); sb.Append("/""); foreach (char nextChar in str) { sb.Append(nextChar); if (nextChar == ''"'') sb.Append("/""); } sb.Append("/""); return sb.ToString(); } return str; }