none
split RRS feed

  • Pregunta

  • Tengo el siguiente problema, necesito separar una linea por comas, esto lo hago con split, hasta ahi todo ok, el problema es que tengo un numero que tiene comas y este no necesito separarlo sino conservar su integridad, hay alguna forma de hacer split con una condicional, este es un ejemplo de lo que tengo que separar 

    30-Oct,Abono Ach Bco Bancajasocial De Upsistemas Sas Nit8001057065",0,"$100,935.00 ",0,BANCA ELECTRONICA,Bogota Cun

    el valor 100,935.00 es el que necesito que no se descomponga con split, alguien me podria decir que alternativa podria usar?

    miércoles, 6 de diciembre de 2017 5:03

Respuestas

  • Siendo un formato de archivo clásico del lenguaje BASIC, no es de extrañar que vb lo lea sin problemas. 

    Usas Input, contra el stream, o usas OpenTextFieldParser contra cada string/fila.

    Sólo debes agregar la referencia.

    // /r: Microsoft.VisualBasic.dll using Microsoft.VisualBasic.FileIO; // ...

    TextFieldParser tfp = new TextFieldParser(@"c:\archivo.dat"); tfp.Delimiters = new string[] { "," }; while (!tfp.EndOfData) { string[] s = tfp.ReadFields(); decimal valor = decimal.Parse(s[3], System.Globalization.NumberStyles.Currency, System.Globalization.CultureInfo.GetCultureInfo("en-us")); }


    Por otro lado, puedes usar un autómata como dice Alberto. El lenguaje es muy sencillo (copias los caracteres al búfer. Cuando hallas una coma, vacías el búfer. Cuando se encuentran comillas, se copia todo lo que se encuentra al búfer hasta dar con otras comillas.), son tres o cuatro estados. Un switch de 3 ó 4 etiquetas con dos o tres líneas cada uno. 

    Algo así

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    
    namespace ConsoleApplication1
    {
        enum Estados { INICIO_COPIA, COPIA_HASTA_COMILLAS, COPIA_HASTA_COMA }
    
        class Program
        {
            static void Main(string[] args)
            {
                string[] archivo = File.ReadAllLines(@"c:\archivo.txt", Encoding.Default);
    
                foreach (string línea in archivo)
                {
                    string[] s = SPLIT(línea);
                }
    
                Console.ReadKey();
            }
    
            private static string[] SPLIT(string s)
            {
                StringBuilder sb = new StringBuilder();
                List<string> lista = new List<string>();
    
                Estados estado = Estados.INICIO_COPIA;
                foreach (char item in s)
                {
                    switch(estado)
                    {
                        case Estados.INICIO_COPIA:
                            if (item == '"') estado = Estados.COPIA_HASTA_COMILLAS;
                            else if (item == ' ') sb.Append(item);
                            else
                            {
                                sb.Append(item);
                                estado = Estados.COPIA_HASTA_COMA;
                            }
                            break;
    
                        case Estados.COPIA_HASTA_COMILLAS:
                            if (item == '"')
                            {
                                estado = Estados.COPIA_HASTA_COMA;
                            }
                            else
                            {
                                sb.Append(item);
                            }
                            break;
    
                        case Estados.COPIA_HASTA_COMA:
                            if (item == ',')
                            {
                                lista.Add(sb.ToString());
                                sb.Clear();
                                estado = Estados.INICIO_COPIA;
                            }
                            else
                            {
                                sb.Append(item);
                            }
                            break;
                    }
                }
    
                if (sb.Length > 0) lista.Add(sb.ToString());
    
                return lista.ToArray();
            }
    
    
        }
    }

    --

    Nada. Ni una miserable palabra. El foro de c# está en ruinas, a merced de una horda de moderators que salen de la nada y nada valen. Los poquísimos moderadores que valen la pena, callan de manera cómplice y tampoco deberíamos ser condescendientes con ellos.



    • Editado HQ56 miércoles, 6 de diciembre de 2017 20:39
    • Propuesto como respuesta Willams Morales jueves, 7 de diciembre de 2017 4:31
    • Votado como útil felipeagm jueves, 7 de diciembre de 2017 15:30
    • Propuesto como respuesta Pablo RubioModerator viernes, 8 de diciembre de 2017 19:27
    • Marcado como respuesta Juan MondragónModerator martes, 12 de diciembre de 2017 19:27
    miércoles, 6 de diciembre de 2017 14:20

Todas las respuestas

  • No se si habrá lo que buscas, te dejo una función que recibe como parámetro un array de strings y devuelve una lista de string con los decimales con su coma.

        private List<string> UnirDecimales(string[] Cadena)
        {
          List<string> rta = new List<string>();
          for (int i = 0; i < Cadena.Length; i++)
          {
            if (i < Cadena.Length - 1)
            {
              Double sDecimal = 0;
              if (double.TryParse(Cadena[i] + "." + Cadena[i + 1], out sDecimal))
              {
                rta.Add(Cadena[i] + "," + Cadena[i + 1]);
                i++;
              }
              else
                rta.Add(Cadena[i]);
            }
            else
              rta.Add(Cadena[i]);
          }
          return rta;
        }

    Lo usas asi por ejemplo:

        private void btnSplit_Click(object sender, EventArgs e)
        {
          string[] Cad = txtCadena.Text.Split(',');
          txtResultado.Text = String.Join(" - ", UnirDecimales(Cad).ToArray());
        }


    • Editado AntiWork miércoles, 6 de diciembre de 2017 10:52
    miércoles, 6 de diciembre de 2017 10:42
  • Y no podrías separar los datos con otro tipo de caracter que no sea comúnmente utilizado como la coma "," por ejemplo podrías utilizar el punto y coma ";" u otro caracter que te sea de utilidad para separar los datos.

    Espero te sirva de ayuda.

    Saludos.


    • Editado osrol miércoles, 6 de diciembre de 2017 11:42
    • Propuesto como respuesta Pablo RubioModerator miércoles, 6 de diciembre de 2017 17:56
    miércoles, 6 de diciembre de 2017 11:41
  • alguien me podria decir que alternativa podria usar?

    Hacerlo BIEN hecho es complicado, necesitarías una máquina de estado que vaya distinguiendo si estamos dentro de un campo o entre medias de campos, usando las dobles comillas que encierran tu número en el ejemplo para distinguir si estamos dentro o fuera de un campo -- con las posibles complicaciones inherentes a la presencia de dobles comillas dentro de un campo, que a su vez tendrían que escaparse. La máquina de estado podrías implementarla a mano, o auxiliarte (por ejemplo) con una expresión regular (donde la máquna de estado está implementada internamente en el motor de expresiones regulares).

    Pero si en lugar de hacerlo bien te conformas con hacer una pequeña chapucilla, puedes usar un IndexOf para buscar ",\"" y detras de éste buscar "\",", y entre medias de esas dos posiciones hacer un Replace de la coma por algún carácter raro. Después haces el Split, y después sobre los resultados cambias de vuelta el carácter raro por la coma.

    • Propuesto como respuesta Pablo RubioModerator miércoles, 6 de diciembre de 2017 17:57
    • Votado como útil felipeagm jueves, 7 de diciembre de 2017 15:31
    miércoles, 6 de diciembre de 2017 12:00
    Moderador
  • Siendo un formato de archivo clásico del lenguaje BASIC, no es de extrañar que vb lo lea sin problemas. 

    Usas Input, contra el stream, o usas OpenTextFieldParser contra cada string/fila.

    Sólo debes agregar la referencia.

    // /r: Microsoft.VisualBasic.dll using Microsoft.VisualBasic.FileIO; // ...

    TextFieldParser tfp = new TextFieldParser(@"c:\archivo.dat"); tfp.Delimiters = new string[] { "," }; while (!tfp.EndOfData) { string[] s = tfp.ReadFields(); decimal valor = decimal.Parse(s[3], System.Globalization.NumberStyles.Currency, System.Globalization.CultureInfo.GetCultureInfo("en-us")); }


    Por otro lado, puedes usar un autómata como dice Alberto. El lenguaje es muy sencillo (copias los caracteres al búfer. Cuando hallas una coma, vacías el búfer. Cuando se encuentran comillas, se copia todo lo que se encuentra al búfer hasta dar con otras comillas.), son tres o cuatro estados. Un switch de 3 ó 4 etiquetas con dos o tres líneas cada uno. 

    Algo así

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    
    namespace ConsoleApplication1
    {
        enum Estados { INICIO_COPIA, COPIA_HASTA_COMILLAS, COPIA_HASTA_COMA }
    
        class Program
        {
            static void Main(string[] args)
            {
                string[] archivo = File.ReadAllLines(@"c:\archivo.txt", Encoding.Default);
    
                foreach (string línea in archivo)
                {
                    string[] s = SPLIT(línea);
                }
    
                Console.ReadKey();
            }
    
            private static string[] SPLIT(string s)
            {
                StringBuilder sb = new StringBuilder();
                List<string> lista = new List<string>();
    
                Estados estado = Estados.INICIO_COPIA;
                foreach (char item in s)
                {
                    switch(estado)
                    {
                        case Estados.INICIO_COPIA:
                            if (item == '"') estado = Estados.COPIA_HASTA_COMILLAS;
                            else if (item == ' ') sb.Append(item);
                            else
                            {
                                sb.Append(item);
                                estado = Estados.COPIA_HASTA_COMA;
                            }
                            break;
    
                        case Estados.COPIA_HASTA_COMILLAS:
                            if (item == '"')
                            {
                                estado = Estados.COPIA_HASTA_COMA;
                            }
                            else
                            {
                                sb.Append(item);
                            }
                            break;
    
                        case Estados.COPIA_HASTA_COMA:
                            if (item == ',')
                            {
                                lista.Add(sb.ToString());
                                sb.Clear();
                                estado = Estados.INICIO_COPIA;
                            }
                            else
                            {
                                sb.Append(item);
                            }
                            break;
                    }
                }
    
                if (sb.Length > 0) lista.Add(sb.ToString());
    
                return lista.ToArray();
            }
    
    
        }
    }

    --

    Nada. Ni una miserable palabra. El foro de c# está en ruinas, a merced de una horda de moderators que salen de la nada y nada valen. Los poquísimos moderadores que valen la pena, callan de manera cómplice y tampoco deberíamos ser condescendientes con ellos.



    • Editado HQ56 miércoles, 6 de diciembre de 2017 20:39
    • Propuesto como respuesta Willams Morales jueves, 7 de diciembre de 2017 4:31
    • Votado como útil felipeagm jueves, 7 de diciembre de 2017 15:30
    • Propuesto como respuesta Pablo RubioModerator viernes, 8 de diciembre de 2017 19:27
    • Marcado como respuesta Juan MondragónModerator martes, 12 de diciembre de 2017 19:27
    miércoles, 6 de diciembre de 2017 14:20