quarta-feira, 13 de abril de 2011

Non-breaking space - Como resolver

Depois de enfrentar arduamente um problema, é natural que a solução se torne óbvia. Será normal que alguém, ao ler esse texto, possa pensar: "Mas eu teria pensado nisso de primeira". Mas sabemos que não é bem assim. Neste caso, o problema envolve o "non-breaking space", ASCII(160). Mais que mostrar a solução, vou colocar o passo a passo do processo de investigação.

O Cenário: Um sistema batch precisa fazer uma carga de dados baseado em um csv que é gerado a partir de uma planilha. Pela descrição encontra o registro correto e altera outros campos.

O Problema: Uma string com o conteúdo "visível" exatamente igual ao campo não era encontrada nem com igual (=) e nem com like.

A Investigação:
Como acredito ser normal nesses casos, verifiquei se o que estava sendo passado como descrição retornava o registro esperado, fazendo a query diretamente na base de dados. Não retornava. Com o like, fui reduzindo os caracteres da string e, em certo momento, o registro era recuperado. Peguei o conteúdo do campo na tabela e substitui na string, voltando a usar apenas o sinal de igualdade. A query retornou o registro, normalmente.

Analisando as duas strings vi que eram, aparentemente, iguais. Coloquei uma string abaixo da outra, olhei fixamente, chamei outras pessoas para olhar, pois eu tinha certeza que já estava meio cego a uma hora da manhã, mas nada. Todos viram a string exatamente iguais. Coloquei no meld, e exatamente iguais.

Neste momento, só restava uma coisa: analisar os codigos ASCII de cada string. Com um pequeno trecho de código, fiz com que todas as referências ASCII das duas strings fossem impressas, joguei no meld e achei a diferença: onde deveria haver um espaço, ASCII(32), havia esse ASCII(160).

Procurando no google, descobri que este código ASCII é referente ao non-breaking space. Agora era resolver. A base de dados e a fonte da carga estavam com o non-breaking space em locais aleatórios. Isso acontecia com todas as strings que não eram encontradas. Era preciso compatibilizar as duas strings envolvidas na busca:

No CSV:
String descricao = partes[0].replaceAll("[\\u00a0]", " ");


Na query:
replace(descricao, chr(160), ' ')

Hoje, estou avaliando incluir esta compatibilização nos sistemas que necessitem comparar duas strings.

Durante as pesquisas, percebi que a inclusão destes caracteres aleatoriamente está normalmente ligada a dados oriundos de planilhas do Microsoft Excel. Assim, atenção especial nestes casos.

Outro ponto interessante é que este caracter é representado como    no HTML, velho conhecido de desenvolvedores WEB.

Nenhum comentário:

Postar um comentário