| using System;
|
| using System.Collections;
|
| using System.Data;
|
| using System.Text;
|
| using System.IO;
|
| using System.Collections.Generic;
|
|
|
| namespace io.csv
|
| {
|
| public class CsvParser
|
| {
|
| #region Atributos/Constantes/Propriedades
|
| private bool _quoted = false;
|
| private bool _headers = false;
|
| private string[] _sHeaders;
|
| private int _col = 1;
|
|
|
| private TextReader _stream;
|
|
|
| #endregion
|
|
|
| #region Construtor
|
|
|
| public CsvParser(TextReader stream, bool headers)
|
| {
|
| _stream = stream;
|
| _headers = headers;
|
| }
|
|
|
| public CsvParser(TextReader stream, string[] headers)
|
| {
|
| _stream = stream;
|
| _sHeaders = headers;
|
| _headers = true;
|
| _col = headers.Length;
|
| }
|
|
|
| #endregion
|
|
|
| #region Métodos
|
|
|
| private void analisarEstrutura(string linha)
|
| {
|
| bool dentroQuotes = false;
|
|
|
| //Verifica se primeiro caracter é "
|
| if (eQuote(linha[0]))
|
| {
|
| _quoted = true;
|
| }
|
|
|
| // Caso tenha passado os hearders via codigo, o numero de colunas já está determinado
|
| if (_sHeaders.Length > 0)
|
| {
|
| // Trata o numero de colunas com Quotes
|
| if (_quoted)
|
| {
|
|
|
| foreach (char c in linha)
|
| {
|
| if (eQuote(c))
|
| {
|
| dentroQuotes = !dentroQuotes;
|
| }
|
| else
|
| {
|
| if (eSeparador(c) && !dentroQuotes)
|
| {
|
| _col++;
|
| }
|
| }
|
| }
|
| }
|
| else
|
| {
|
| // Trata o numero de colunas sem Quotes
|
| foreach (char c in linha)
|
| {
|
| if (eSeparador(c))
|
| {
|
| _col++;
|
| }
|
| }
|
|
|
| }
|
| }
|
| } //analisarEstrutura
|
|
|
| private bool eQuote(char c)
|
| {
|
| return c == '"';
|
| } //eQuote
|
|
|
| private bool eSeparador(char c)
|
| {
|
| return c == ',' || c == ';';
|
| } //eSeparador
|
|
|
| public bool parser(out DataTable dataTable, Usuario usuario)
|
| {
|
|
|
| DataTable dt = new DataTable();
|
| string[] cabecalhos;
|
| string[] tokens;
|
| bool sucesso;
|
|
|
| sucesso = true;
|
|
|
| // Para aumentar a eficiencia poderia usar o ReadBlock ao inves do ReadLine
|
| // lendo assim uma quantidade de caracteres maiores a cada "ida" ao arquivo (buffer)
|
| // porém teria que tratar a quebra de linha
|
| string linha = _stream.ReadLine();
|
|
|
|
|
| // Analisando a Estrutura
|
| analisarEstrutura(linha);
|
|
|
| // Processa cabecalho
|
| if (_headers)
|
| {
|
| // headers passado via codigo
|
| if (_sHeaders.Length > 0)
|
| {
|
| foreach (string s in _sHeaders)
|
| {
|
| dt.Columns.Add(s, typeof(string));
|
| }
|
| }
|
| else
|
| {
|
| //Processa cabecalhos com texto da primeira linha
|
| cabecalhos = getTokens(linha);
|
| foreach (string s in cabecalhos)
|
| {
|
| dt.Columns.Add(s, typeof(string));
|
| }
|
| }
|
| }
|
| else
|
| {
|
| //Processa cabecalho sem texto
|
| for (int i = 0; i < _col; i++)
|
| {
|
| dt.Columns.Add(String.Format("Coluna {0}", i + 1), typeof(string));
|
| }
|
|
|
| //Processa primeira linha
|
| dt.Rows.Add(getTokens(linha));
|
|
|
| }
|
|
|
| while ((linha = _stream.ReadLine()) != null)
|
| {
|
| tokens = getTokens(linha);
|
| if (tokens.Length > _col)
|
| {
|
| // Erro! Linha fora do padrão
|
| sucesso = false;
|
| break;
|
|
|
| }
|
| else
|
| {
|
| dt.Rows.Add(tokens);
|
| }
|
| }
|
|
|
| if (sucesso)
|
| {
|
| dataTable = dt;
|
| }
|
| else
|
| {
|
| dataTable = null;
|
| }
|
|
|
| return sucesso;
|
| } //Parser
|
|
|
| private string[] getTokens(string linha)
|
| {
|
| bool dentroQuotes = false;
|
| List<String> tokens = new List<string>();
|
| StringBuilder sb = new StringBuilder();
|
|
|
| if (_quoted)
|
| {
|
| // Tratando caso com quotes
|
|
|
| foreach (char c in linha)
|
| {
|
| // é "
|
| if (eQuote(c))
|
| {
|
| dentroQuotes = !dentroQuotes;
|
| }
|
| else
|
| {
|
| // Caso esteja dentro da area delimitada por " faz o append do caracter
|
| if (dentroQuotes)
|
| {
|
| sb.Append(c);
|
| }
|
| else
|
| {
|
| // Fora da area delimitada pela " e encontrou um separador, salva a string na lista
|
| if (eSeparador(c))
|
| {
|
| tokens.Add(sb.ToString());
|
| sb = new StringBuilder();
|
| }
|
| }
|
| }
|
| }
|
| // Acabou de ler a linha sem ler um separador
|
| // adiciona no vetor os caracteres que ainda estao no SB
|
| tokens.Add(sb.ToString());
|
| }
|
| else
|
| {
|
| // Tratando caso sem quotes
|
|
|
| foreach (char c in linha)
|
| {
|
| // Caso seja separador, indica uma nova palavra foi encontrada
|
| // Adiciona ela na lista e reinicia o StringBuilder
|
| if (eSeparador(c))
|
| {
|
| tokens.Add(sb.ToString());
|
| sb = new StringBuilder();
|
| }
|
| }
|
| // Acabou de ler a linha sem ler um separador
|
| // adiciona no vetor os caracteres que ainda estao no SB
|
| tokens.Add(sb.ToString());
|
| }
|
| return tokens.ToArray();
|
| } //getTokens
|
|
|
| #endregion
|
|
|
| } //CsvReader
|
|
|
| } //namespace |