Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Problemas quando leio e gravo uma conta no CSV

Olá Guilherme! Estou com alguns problemas no meu exercício pessoal desse módulo. Na hora de escrever uma conta corrente no CSV e ler ele. Vou explicar:

Tenho uma classe Bank que tem todas as abstrações para eu criar essa conta corrente. Quando crio, ele verifica se a linha já existe no CSV, adicionando lá caso contrário. Até aí tudo bem. O problema é que quando crio a string (exemplo:

(exemplo: )

var LinhaCSV = {$"Numero}, {Saldo}, {bClienteMulher}, {Nome}"

sendo saldo (100.50) o double é escrito como (100,50) no bloco de notas e aí meu

split(',') 

pega essa vírgula, passa um array de 5 elementos ao invés de 4, manda um "50" pra bool e dispara uma exceção (SystemFormatException). Gostaria de saber como eu poderia resolver isso mantendo a vírgula como separador ao invés de usar outro char como o pipe '|' que já foge do padrão CSV.

Outra situação que acontece é que, durante alguma escrita (cerca de 2 ou 3 nomes escritos)no bloco de notas, o StreamWriter está jogando alguns caracteres aleatórios nos campos da string. Ae toda vez que abro o .exe que ele tenta carregar os objetos anteriores, ele tenta dar um

int.Parse()

e ele dispara o mesmo tipo de exceção, pois esses caracteres estranhos deformam a string e ele n consegue dar um parse de int.

Aqui vou deixar aqui meu código fonte: https://drive.google.com/open?id=1wTxO4guTyOGSem_U9ORoD52IwcReD6s1

3 respostas

Opa, Murilo. Tudo bom?

O ToString de uma variável do tipo ponto flutuante sai com uma vírgula como separador ao invés de um ponto porque nossas máquinas estão configuradas com a cultura de data/hora/valores numéricos da cultura brasileira com a língua portuguesa (pt-BR).

A solução para isto é usar uma cultura diferente. Podemos usar a cultura invariante, que é a cultura associada ao inglês mas nenhum país específico:

using System.Globalization;

...

var numero = 10.5;
var cultura = CultureInfo.InvariantCulture;
var numeroComoTexto = numero.ToString(cultura);
Console.WriteLine(numeroComoTexto); // 10.5

Sobre o outro problema, percebi no seu código que em Bank::CreateBankAccount você tem o código abaixo:

using (AccountRegistry = File.Open(AccountRegistryFilePath, FileMode.Open, FileAccess.Write))
using (var Writer = new StreamWriter(AccountRegistry, Encoding.UTF8))
{
    AccountRegistry.Seek(0, SeekOrigin.End);
    Writer.WriteLine(Registry);
    Writer.Flush();
}

Acho que você está utilizando o AccountRegistry.Seek para mudar a posição do stream para o fim do arquivo, correto? Você pode fazer isto usando o FileMode.Append, tente com:

using (AccountRegistry = File.Open(AccountRegistryFilePath, FileMode.Append, FileAccess.Write))
using (var Writer = new StreamWriter(AccountRegistry, Encoding.UTF8))
{
    Writer.WriteLine(Registry);
}

(eu também removi a chamada para o Flush, porque na chamada do Dispose feita ao fim do bloco using, o flush é chamado)

Funcionou?

Fico no aguardo, abs.

Perfeito!

Agora funciona perfeitamente! Acredito que o problema anterior quanto aos "caracteres estranhos" seja por causa do BOM(Byte Order Mark) gerado pelo Seek. É possível a gente não escrever eles em hipótese alguma quando usando o StreamWriter::Seek()? Já vi gente escrevendo um código a parte para filtrar a linha, mas entra naquele problema: Eu não vou jogar todos esses dados na Ram para fazer esse filtro pois pode acontecer dela não ser suficiente caso tenho muitos dados para analisar.

solução!

Sim!

Quando você usa o encoding UTF8 pelo membro estático Encoding.UTF8 não pode controlar se o BOM é emitido ou não. Mas, o construtor da classe UTF8Encoding tem esse argumento, como vemos na documentação.

Então o código ficaria:

using (var Writer = new StreamWriter(AccountRegistry, new UTF8Encoding(false))

No lugar de:

using (var Writer = new StreamWriter(AccountRegistry, Encoding.UTF8))