Estou procurando sugestões sobre como lidar com um arquivo csv que está sendo criado e carregado por nossos clientes e que pode ter vírgula em um valor, como o nome da empresa.
Algumas das idéias que estamos analisando são: Identificadores entre aspas (valor "," valores "," etc ") ou usar um | em vez de vírgula. O maior problema é que precisamos facilitar as coisas ou o cliente não o fará.
Respostas:
Como já foi dito, você precisa escapar de valores que incluem aspas. Aqui está um pequeno leitor de CSV em C♯ que suporta valores entre aspas, incluindo cotações incorporadas e retornos de carro.
A propósito, esse é um código testado por unidade. Estou postando agora porque essa pergunta parece surgir muito e outras pessoas podem não querer uma biblioteca inteira quando o suporte simples a CSV for necessário.
Você pode usá-lo da seguinte maneira:
Aqui estão as aulas. Observe que você também pode usar a
Csv.Escape
função para gravar CSV válido.fonte
Para 2017, o csv está totalmente especificado - RFC 4180.
É uma especificação muito comum e é completamente coberta por muitas bibliotecas ( exemplo ).
Basta usar qualquer biblioteca csv facilmente disponível - ou seja, RFC 4180.
Na verdade, há uma especificação para o formato CSV e como lidar com vírgulas:
http://tools.ietf.org/html/rfc4180
Então, para ter valores
foo
ebar,baz
, faça o seguinte:Outro requisito importante a ser considerado (também das especificações):
fonte
System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator
.O formato CSV usa vírgulas para separar valores, valores que contêm retornos de carro, alimentações de linha, vírgulas ou aspas duplas são cercados por aspas duplas. Os valores que contêm aspas duplas são citados e cada citação literal é escapada por uma citação imediatamente anterior: por exemplo, os 3 valores:
seria codificado como:
Qualquer campo pode ser citado, mas apenas os que contêm vírgulas, CR / NL ou aspas devem ser citados.
Não existe um padrão real para o formato CSV, mas quase todos os aplicativos seguem as convenções documentadas aqui . A RFC mencionada em outro lugar não é um padrão para CSV, é uma RFC para usar CSV no MIME e contém algumas limitações não convencionais e desnecessárias que o tornam inútil fora do MIME.
Um problema que muitos módulos CSV que eu vi não acomodam é o fato de que várias linhas podem ser codificadas em um único campo, o que significa que você não pode assumir que cada linha é um registro separado, ou você não deve permitir novas linhas no seu dados ou esteja preparado para lidar com isso.
fonte
Coloque aspas duplas em torno de strings. Isso geralmente é o que o Excel faz .
Ala Eli,
fonte
Você pode colocar aspas duplas nos campos. Não gosto dessa abordagem, pois acrescenta outro caractere especial (aspas duplas). Basta definir um caractere de escape (geralmente barra invertida) e usá-lo sempre que precisar escapar de algo:
Você não precisa tentar corresponder aspas e possui menos exceções para analisar. Isso simplifica seu código também.
fonte
Existe uma biblioteca disponível através do nuget para lidar com praticamente qualquer CSV bem formado (.net) - CsvHelper
Exemplo para mapear para uma classe:
Exemplo para ler campos individuais:
Permitir que o cliente conduza o formato do arquivo:
,
é o delimitador de campo padrão,"
é o valor padrão usado para escapar dos campos que contêm um delimitador, cotação ou final de linha.Para usar (por exemplo)
#
para campos e'
para escapar:Mais documentação
fonte
CsvHelper
biblioteca para resolver o problema do OP.Como mencionado no meu comentário à resposta do harpo, sua solução é boa e funciona na maioria dos casos, no entanto, em alguns cenários, quando as vírgulas são diretamente adjacentes uma à outra, ela não se divide nas vírgulas.
Isso ocorre porque a string Regex se comporta inesperadamente como uma string vertabim. Para que isso se comporte corretamente, todos os caracteres "na sequência de caracteres regex precisam ser escapados manualmente sem usar o escape vertabim.
Ou seja. O regex deve ser este usando escapes manuais:
",(?=(?:[^\"\"]*\"\"[^\"\"]*\"\")*(?![^\"\"]*\"\"))"
que se traduz em
",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
Ao usar uma sequência vertabim,
@",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
ele se comporta da seguinte maneira, como você pode ver se você depura o regex:Então, em resumo, eu recomendo a solução do harpo, mas cuidado com essa pequena pegadinha!
Incluímos no CsvReader um pouco de segurança opcional para notificá-lo se esse erro ocorrer (se você tiver um número pré-conhecido de colunas):
Isso pode ser injetado através do construtor:
fonte
[^""]
o mesmo que[^"]
? A duplicação de um caractere dentro de uma especificação de classe de caractere é redundante, certo?Adicione uma referência ao Microsoft.VisualBasic (sim, ele diz VisualBasic, mas também funciona em C # - lembre-se de que, no final, tudo é apenas IL).
Use a
Microsoft.VisualBasic.FileIO.TextFieldParser
classe para analisar o arquivo CSV Aqui está o código de exemplo:fonte
parser.HasFieldsEnclosedInQuotes = true;
e o arquivo de entrada precisará incluir campos que contenham vírgulas entre aspas conforme a especificação do CSV - o Excel já faz isso.Você pode usar "delimitadores" alternativos como ";" ou "|" mas o mais simples pode ser citado, suportado pela maioria das bibliotecas CSV (decentes) e pelas planilhas mais decentes.
Para obter mais informações sobre delimitadores CSV e uma especificação para um formato padrão para descrever delimitadores e cotações, consulte esta página da web.
fonte
Caso você esteja em um sistema * nix , tenha acesso
sed
e possa haver uma ou mais vírgulas indesejadas apenas em um campo específico do seu CSV, use a seguinte linha para incluí-las"
como RFC4180. 2 propõe:Dependendo de qual campo a (s) vírgula (s) indesejada (s) pode estar, você deve alterar / estender os grupos de captura da expressão regular (e a substituição).
O exemplo acima incluirá o quarto campo (de seis) entre aspas.
Em combinação com a
--in-place
opção- você pode aplicar essas alterações diretamente no arquivo.Para "construir" a regex correta, existe um princípio simples a seguir:
[^,]*,
e junta todos eles em um grupo de captura.(.*)
.,.*
e junta todos eles em um grupo de captura.Aqui está uma breve visão geral das diferentes regexes / substituições possíveis, dependendo do campo específico. Se não for dado, a substituição é
\1"\2"\3
.Se você deseja remover as vírgulas indesejadas, em
sed
vez de colocá-las entre aspas, consulte esta resposta .fonte
Se você deseja reinventar a roda, o seguinte pode funcionar para você:
fonte
Na Europa, temos esse problema antes que esta questão. Na Europa, usamos todas as vírgulas para um ponto decimal. Veja estes números abaixo:
Portanto, não é possível usar o separador de vírgulas para arquivos CSV. Por esse motivo, os arquivos CSV na Europa são separados por ponto e vírgula (
;
) .Programas como o Microsoft Excel podem ler arquivos com ponto e vírgula e é possível alternar do separador. Você pode até usar uma tab (
\t
) como separador. Veja esta resposta do usuário Ceia .fonte
Se você estiver interessado em um exercício mais educacional sobre como analisar arquivos em geral (usando o CSV como exemplo), consulte este artigo de Julian Bucknall. Gosto do artigo porque divide as coisas em problemas muito menores e muito menos intransponíveis. Você primeiro cria uma gramática e, depois de ter uma boa gramática, é um processo relativamente fácil e metódico converter a gramática em código.
O artigo usa C # e tem um link na parte inferior para baixar o código.
fonte
Aqui está uma pequena solução:
Você pode usar um sinal numérico inferior grego (U + 0375)
Parece assim ͵
O uso desse método poupa muitos recursos também ...
fonte
Basta usar o SoftCircuits.CsvParser no NuGet. Ele lida com todos esses detalhes e lida com eficiência com arquivos muito grandes. E, se necessário, ele pode até importar / exportar objetos mapeando colunas para as propriedades do objeto. Além disso, meus testes mostraram que a média é quase 4 vezes mais rápida que o popular CsvHelper.
fonte
Como se trata de práticas gerais, vamos começar pelas regras básicas:
Não use CSV, use XML com uma biblioteca para ler e gravar o arquivo xml.
Se você deve usar o CSV. Faça-o corretamente e use uma biblioteca gratuita para analisar e armazenar os arquivos CSV.
Para justificar 1), a maioria dos analisadores CSV não tem conhecimento de codificação; portanto, se você não está lidando com US-ASCII, está solicitando problemas. Por exemplo, o Excel 2002 está armazenando o CSV na codificação local sem nenhuma observação sobre a codificação. O padrão CSV não é amplamente adotado :(. Por outro lado, o padrão xml é bem adotado e lida com codificações muito bem.
Para justificar 2), existem muitos analisadores csv em quase todo o idioma, portanto, não há necessidade de reinventar a roda, mesmo que as soluções pareçam bastante simples.
Para citar alguns:
para python use build no módulo csv
para perl, verifique CPAN e Text :: CSV
para php use build em funções fgetcsv / fputcsv
para biblioteca Java SuperCVS
Realmente, não há necessidade de implementar isso manualmente, se você não for analisá-lo no dispositivo incorporado.
fonte
Você pode ler o arquivo csv assim.
isso faz uso de divisões e cuida dos espaços.
fonte
Primeiro, vamos nos perguntar: "Por que sentimos a necessidade de manipular vírgulas de maneira diferente para arquivos CSV?"
Para mim, a resposta é: "Quando eu exporto dados para um arquivo CSV, as vírgulas em um campo desaparecem e meu campo é separado em vários campos, onde as vírgulas aparecem nos dados originais". (Isso porque a vírgula é o caractere separador de campo CSV.)
Dependendo da sua situação, pontos e vírgulas também podem ser usados como separadores de campo CSV.
Dado os meus requisitos, posso usar um caractere, por exemplo, aspas simples de 9, que se parece com uma vírgula.
Então, veja como você pode fazê-lo no Go:
O segundo caractere de vírgula na função Substituir é decimal 8218.
Esteja ciente de que, se você tiver clientes que podem ter leitores de texto apenas ascii, esse caractere dizimado 8218 não parecerá uma vírgula. Se esse for o seu caso, recomendo colocar o campo com uma vírgula (ou ponto-e-vírgula) com aspas duplas conforme a RFC 4128: https://tools.ietf.org/html/rfc4180
fonte
Geralmente codifico por URL os campos que podem ter vírgulas ou caracteres especiais. E então decodifique quando estiver sendo usado / exibido em qualquer meio visual.
(vírgulas se tornam% 2C)
Todo idioma deve ter métodos para codificar e decodificar URLs.
por exemplo, em java
Eu sei que esta é uma solução muito geral e pode não ser ideal para situações em que o usuário deseja visualizar o conteúdo do arquivo csv manualmente.
fonte
Normalmente, faço isso nos meus arquivos CSV, analisando as rotinas. Suponha que a variável 'linha' seja uma linha dentro de um arquivo CSV e os valores de todas as colunas estejam entre aspas duplas. Após a execução das duas linhas abaixo, você obterá colunas CSV na coleção 'values'.
fonte
A solução mais simples que encontrei é a que o LibreOffice usa:
"
por”
Você também pode usar aquele que o Excel usa:
"
por""
Observe que outras pessoas recomendaram executar apenas a etapa 2 acima, mas isso não funciona com as linhas em que a
"
é seguido por a,
, como em um CSV em que você deseja ter uma única coluna com a stringhello",world
, como leria o CSV:Que é interpretado como uma linha com duas colunas:
hello
eworld"
fonte
hello",world
campo simplesmente precisaria ser salvo como"hello"",world"
, que pode ser analisado 100% corretamente.fonte
Eu usei a biblioteca Csvreader, mas usando isso, obtive dados explodindo a partir da vírgula (,) no valor da coluna.
Portanto, se você deseja inserir dados do arquivo CSV que contenham vírgula (,) na maioria dos valores das colunas, use a função abaixo. Autor link => https://gist.github.com/jaywilliams/385876
fonte
Usei a biblioteca papaParse para analisar o arquivo CSV e ter os pares de valores-chave (chave / cabeçalho / primeira linha do valor do arquivo CSV).
Aqui está um exemplo que eu uso:
https://codesandbox.io/embed/llqmrp96pm
ele possui o arquivo dummy.csv para ter a demonstração de análise de CSV.
Eu o usei no reactJS, embora seja fácil e simples replicar no aplicativo escrito em qualquer idioma.
fonte
Um exemplo pode ajudar a mostrar como as vírgulas podem ser exibidas em um arquivo .csv. Crie um arquivo de texto simples da seguinte maneira:
Salve este arquivo de texto como um arquivo de texto com o sufixo ".csv" e abra-o com o Excel 2000 no Windows 10.
aa, bb, cc, d; d "Na apresentação da planilha, a linha abaixo deve se parecer com a linha acima, exceto que a abaixo mostra uma vírgula exibida em vez de um ponto e vírgula entre os ds." aa, bb, cc, "d, d", isso funciona mesmo no Excel
aa, bb, cc, "d, d", funciona mesmo no Excel 2000 aa, bb, cc, "d, d", funciona mesmo no Excel 2000 aa, bb, cc, "d, d", funciona mesmo no Excel 2000
aa, bb, cc, "d, d", Isso falha no Excel 2000 devido ao espaço antes da 1ª cotação aa, bb, cc, "d, d", isso falha no Excel 2000 devido ao espaço antes da 1ª cotação aa, bb, cc, "d, d", isso falha no Excel 2000 devido ao espaço existente na primeira cotação
aa, bb, cc, "d, d", Isso funciona mesmo no Excel 2000, mesmo com espaços antes e depois da segunda cotação. aa, bb, cc, "d, d", Isso funciona mesmo no Excel 2000, mesmo com espaços antes e depois da segunda cotação. aa, bb, cc, "d, d", Isso funciona mesmo no Excel 2000, mesmo com espaços antes e depois da segunda cotação.
Regra: Se você deseja exibir uma vírgula em uma célula (campo) de um arquivo .csv: "Inicie e termine o campo com aspas duplas, mas evite o espaço em branco antes da primeira cotação"
fonte
Acho que a solução mais fácil para esse problema é ter o cliente para abrir o csv no excel e, em seguida, pressionar a tecla Ctrl + r para substituir toda a vírgula pelo identificador desejado. Isso é muito fácil para o cliente e requer apenas uma alteração no seu código para ler o delimitador de sua escolha.
fonte
Use um caractere de tabulação (\ t) para separar os campos.
fonte