Contar caracteres

Bom dia Pessoal.

estou com o seguinte código, para contar o numero de caracteres de um arquivo, no entanto ele não está contando todos, ao meu ver os espaços e alguns outros caracteres que não sejam letras ele não conta.
no meu ex. o arquivo tem 270 bytes, o codigo tá me dizendo que são 206.
podem me ajudar?

import java.io.BufferedReader;

public class ContadorDeCaracteres {
public static void main(String args[]) throws Exception {
BufferedReader arquivo = new BufferedReader(new java.io.FileReader(“D:\SystemCheckOut.txt”));
String linha=null;
int Caracteres = 0;
while (arquivo.ready()) {
try{
linha=arquivo.readLine();
Caracteres += linha.length();
}catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println("numero de caracteres "+Caracteres);
}
}

Atenciosamente.

[quote]readLine

public String readLine()
throws IOException

Read a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.[/quote]

Ou seja, acho que vc tem de adicionar um caracter a cada linha!

[quote=franchico]Bom dia Pessoal.

estou com o seguinte código, para contar o numero de caracteres de um arquivo, no entanto ele não está contando todos, ao meu ver os espaços e alguns outros caracteres que não sejam letras ele não conta.
no meu ex. o arquivo tem 270 bytes, o codigo tá me dizendo que são 206.
podem me ajudar?

import java.io.BufferedReader;

public class ContadorDeCaracteres {
public static void main(String args[]) throws Exception {
BufferedReader arquivo = new BufferedReader(new java.io.FileReader(“D:\SystemCheckOut.txt”));
String linha=null;
int Caracteres = 0;
while (arquivo.ready()) {
try{
linha=arquivo.readLine();
Caracteres += linha.length();
}catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println("numero de caracteres "+Caracteres);
}
}

Atenciosamente.[/quote]

Amigo, esses 270 pode ser devido ao tamanho do cluster do disco rígido. Por exemplo, se o SO precisa armazenar uma palavra de 8 bytes em um cluster de 64 bytes, o SO usará todos os 64 bytes do cluster para essa palavra. Pode reparar que se você colocar esse mesmo arquivo numa pen-drive ele ficará com tamanho diferente. Não sei se você está levando em consideração isso. Caso já esteja, desconsidere a minha mensagem.

Se não estiver levando em consideração, dá uma procurada em Arquitetura de Computadores - Armazenamento, para maiores (e melhores) esclarecimentos.

Outra opção, para acabar definitivamente com as dúvidas, seria usar uma forma de mais baixo nível para ler o arquivo. Uso isso para ler uns anexos meio doido que recebo, de informação de GPS. O IF é maior (tem vários else), mas acho que esse dá para exemplificar:

Object o = mensagens[i].getContent();
if (o instanceof InputStream){
  char ch;
  leitor = new BufferedReader(new InputStreamReader((InputStream)o));

  int m = -1;
  String anexo = "";
  while (true){
    try {
      m = leitor.read();
    }catch(Exception e) {
      e.printStackTrace();
    }
						
    if (m == -1)
      break;

    bits += Converte.decToBin(m);
    ch = (char)m;
    anexo += ch;
}

Esse código tem uns 150 anos mais ou menos, e nunca foi refatorado. Está lá jogado numa pasta num CD numa gaveta em uma prateleira.

parece que não é só isso, mas de qualquer forma valeu

a resposta anterior fui para o luis.
Claudio, obrigado vou analisar sua instrução.
obrigado.

Desculpe, mas agora fiquei confuso, vc tá catando o número de byte, através do caracters??? Pq vc num faz simplismente isso?

   File file = new File("infilename"); 
   long length = file.length();

Luiz,

Deixe-me explicar melhor, talvez eu esteja confuso.
Eu preciso comparar a quantidade de caracteres de dois arquivos, então eu to pensando assim:
Eu descubro quantos caracteres tenho em um, depois vejo quantos tem no outro e… futuramente, vejo se os dois teem os mesmos caracteres, talvez a lógica que estou usando esteja errada. Será que existe uma forma mais fácil, ou é assim mesmo?
Valeu,

O tempo passa, as linguagens evoluem. Saímos das linguagens baseadas em caracteres Ascii e agora entramos na era Unicode. Entretanto, algumas pessoas ainda tratam strings como os velhos caracteres de 7 bits do passado.

No mundo Unicode, o quão longa é uma String?

Você pode estar tentando a dizer: Fácil, simplesmente use o método length() para isso. Geralmente, a resposta estará correta, mas esse não é o único meio, e também nem sempre é o meio correto. Na verdade, existem três maneiras de se obter o tamanho de uma String:

Você pode obter o número de unidades de char;
Você pode obter o número de caracteres ou code points;
Você pode obter o número de bytes.

Contando o unidades de char

O java usa o padrão Unicode para definir seus caracteres. A definição inicial do unicode era de caracteres de tamanho fixo, com 16 bits, entre U+0000 até U+FFFF - o símbolo U+ significa um caracter válido Unicode, representado em seguida pro seu código hexadecimal. Convenientemente e não por acaso, o java adotou uma largura fixa de dois bytes para o tipo char. Assim, um char representa qualquer caracter de 16 bits.

A maior parte dos programadores é familiar com o metodo length. O código a seguir conta o número de caracteres numa string de exemplo. Note que essa String possui uma série de caracteres simples e alguns definidos com a notação \u. A notação \u é a equivalente em Java ao padrão unicode U+, e é usada para definir um caracter unicode de 16 bits através de sua notação hexadecimal.

private String testString = "abcdu5B66uD800uDF30"; int charCount = testString.length(); System.out.printf("caracteres: %dn", charCount);
O método Length conta o número de caracteres na String.
O código de exemplo imprime: caracteres: 7

Contando unidades de caracteres (ou code points)
Entretanto, anos mais tarde o padrão Unicode 4.0 definiu um número significativamente maior do que U+FFFF. Isso fez com que o Java passasse a ser incapaz de de representar todos os caracteres. A solução para esse problema surgiu a partir do Java 5, quando pares de chars de 16 bits passaram a ser utilizados para representar um caracter unicode. Esses pares passaram a ser conhecidos como pares substitutos (surrogate pairs).

Apesar de um char ainda poder representar um caracter unicode até U+FFFF, apenas um par pode representar caracteres suplementares. Os valores suplementares possuem o valor mais alto do par no intervalo entre U+DC00 até U+DFFF. O padrão também define um algoritmo para mapear entre um par substituto e um caracter acima de U+FFFF. Com esses pares é possível representar qualquer caracter no padrão Unicode. Mas isso também significa que um caracter de bits pode ser uma unidade de código que não representa um caracter completo unicode (code point).

O método length() não conta os caracteres suplementares, pois ele apenas conta unidades char, sem se preocupar com que eles significam. Os programadores do Java 5 forneceram então um novo método, chamado codePointCount(int beginIndex, int endIndex) capaz de lidar com essa tarefa. Esse método informa quantos caracteres Unicode estão entre os dois indices. Os índices referem-se a unidades de char, como no método length().

Dessa forma, se você subtrair endIndex - begin index para a totalidade de uma String, obterá o mesmo valor que o método length(). Entretanto, esse valor poderá ser completamente diferente do valor de retorno do método codePointCount. Se o seu texto contiver pares substitutos, o tamanho retornado por length() e pelo método codePointCount certamente será diferente. Um surrogate pair define um único code point, mas pode ser definido por uma ou duas unidades de caracteres.

Vejamos um exemplo:

private String testString = "abcdu5B66uD800uDF30"; int charCount = testString.length(); int characterCount = testString.codePointCount(0, charCount); System.out.printf("Número de caracteres: %dn", characterCount);

Esse exemplo imprime:
Número de caracteres: 6

A variável testString contém dois caracteres interessantes, que são os ideogramas japoneses significando ?aprendizado? e um caracter chamado GOTHIC LETTER AHSA. A letra japonesa tem o valor unicode U+5B66, que pode ser representada por apenas um caracter unicode. Entretanto, a letra gótica tem o valor representado pelo par \uD800\uDF30. Como esse par representa apenas um caracter unicode, o valor total de caracteres na String é 6, e não 7.

Contando o número de Bytes
Quantos bytes tem uma String? A resposta varia de acordo com o charset utilizado. A razão para que isso seja perguntado, geralmente é satisfazer o tamanho de um campo num banco de dados. O método getBytes() converte os caracteres Unicode em uma representação orientada a bytes, retornando um byte[]. Uma codificação orientada a bytes é a UTF8, que é diferente de todas as representações unicode pois pode representar de maneira adequada qualquer code point Unicode.

O código abaixo converte o texto num array de bytes:

byte[] utf8 = null; int byteCount = 0; try { utf8 = str.getBytes("UTF-8"); byteCount = utf8.length; } catch (UnsupportedEncodingException ex) { ex.printStackTrace(); }
System.out.printf(“Número de bytes em UTF-8: %dn”, byteCount);O charset destino ( UTF8 ) é quem define quantos bytes serão gerados. O UTF8 transforma um code point unicode em uma até quadro unidades de código de 8 bits (um byte). Assim, os caracteres a, b, c e d juntos requerem apenas um total de quatro bytes. O caracter japonês passa a representar 3 bytes. Finalmente a letra Gótica representa quatro bytes. O resultado total exibido é esse:

Número de bytes em UTF8 Byte: 11

Em resumo
A menos que você utilize caracteres suplementares, você nunca verá diferença entre os valores de retorno de length e codePointCount. Entretanto, caso você queira enviar seus produtos para a crescente China ou para o Japão, você certamente se deparará com esse tipo de caracter, e ficará muito satisfeito por saber que esse método existe.

Transmissões de rede, ou gravações em bancos de dados, recomendam o formato UTF8. Nesse caso, mais uma vez o tamanho da String irá variar enormemente.

Vários métodos para avaliar o tamanho foram apresentados, agora, cabe a você analisar qual é a opção correta para medir sua String.

[quote=franchico]Luiz,

Deixe-me explicar melhor, talvez eu esteja confuso.
Eu preciso comparar a quantidade de caracteres de dois arquivos, então eu to pensando assim:
Eu descubro quantos caracteres tenho em um, depois vejo quantos tem no outro e… futuramente, vejo se os dois teem os mesmos caracteres, talvez a lógica que estou usando esteja errada. Será que existe uma forma mais fácil, ou é assim mesmo?
Valeu, [/quote]

pelo que eu entendi, vc ta querendo a quantidade pra evitar ter de comparar caracter por caracter de todos arquivos, eu faria com o método hashCode() da classe String, a idéia é que se o hashCode da String do conteúdo é igual então o conteúdo é igual, e vc só guarda o hashCode para comparar num prescisa ficar comparando o conteúdo diretamente.

Como todo programador é muito vaidoso, antes que vc fique puto pq eu tô me metendo da sua lógica, não sou dono da verdade, sou só um cara tentando te ajudar!

Ainda sim, tem que tomar cuidado. Hashcodes iguais podem ser gerados para strings de valores diferentes. O Thingol postou a um tempo atrás aqui alguns exemplos.

[quote=ViniGodoy][quote=LuizClaudio]
pelo que eu entendi, vc ta querendo a quantidade pra evitar ter de comparar caracter por caracter de todos arquivos, eu faria com o método hashCode() da classe String, a idéia é que se o hashCode da String do conteúdo é igual então o conteúdo é igual, e vc só guarda o hashCode para comparar num prescisa ficar comparando o conteúdo diretamente.
[/quote]

Ainda sim, tem que tomar cuidado. Hashcodes iguais podem ser gerados para strings de valores diferentes. O Thingol postou a um tempo atrás aqui alguns exemplos.[/quote]

ViniGodoy vc lembra qual era o título do post?

franchico, então se o Hashcode for igual vc compara o conteúdo, mesmo assim ainda melhor do que contar os caracteres, pelo menos eu acho?

[quote=ViniGodoy][quote=LuizClaudio]
pelo que eu entendi, vc ta querendo a quantidade pra evitar ter de comparar caracter por caracter de todos arquivos, eu faria com o método hashCode() da classe String, a idéia é que se o hashCode da String do conteúdo é igual então o conteúdo é igual, e vc só guarda o hashCode para comparar num prescisa ficar comparando o conteúdo diretamente.
[/quote]

Ainda sim, tem que tomar cuidado. Hashcodes iguais podem ser gerados para strings de valores diferentes. O Thingol postou a um tempo atrás aqui alguns exemplos.[/quote]

Vini, aquela solução com while que eu passei, não contaria os caracteres do arquivo, independentemente de qualquer variação, mencionada naquela sua ótima explicação, mensagens atrás?

ViniGodoy

Pelo que vi, são otimas informações, vou estudá-las calmamente, não sou tão expert nisso, uma vez que, faz pouco tempo que conheco o java, mas te agradeço de coração e espero poder contar contigo para futuras dúvidas.

Um Abraço.

[quote=celso.martins]
Vini, aquela solução com while que eu passei, não contaria os caracteres do arquivo, independentemente de qualquer variação, mencionada naquela sua ótima explicação, mensagens atrás?[/quote]

Se o encoding do seu reader bater com o encoding do arquivo, sim.
Mas postei o artigo porque normalmente não sabemos exatamente nem o que estamos contando… e isso pode ser um problema sério.

Por exemplo, se você, na intenção de ficar no baixo nível, usasse um stream no lugar do reader, estaria também contando bytes, não caracteres. E, como está lá em cima, certos caracteres iguais tem representações diferentes.

Ótimo artigo por sinal. Bem esclarecedor. Mereceu até a favoritada deste tópico, para uma leitura mais tranquila, na chegada ao lar.

Vlw!

[quote=celso.martins]
Ótimo artigo por sinal. Bem esclarecedor. Mereceu até a favoritada deste tópico, para uma leitura mais tranquila, na chegada ao lar.
Vlw![/quote]

Esse artigo eu tinha postado para o meu blog, juntamente com outro, também sobre Strings.
Mas decidi focar agora no desenvolvimento de games.

[quote=ViniGodoy]

Esse artigo eu tinha postado para o meu blog, juntamente com outro, também sobre Strings.
Mas decidi focar agora no desenvolvimento de games. [/quote]

Mais um blog pro meu Google Reader :wink:

Vini, realmente essa materia sua ficou show. Acho que valeu ter ficado alguns minutos lendo essa materia, aprendi bastante coisas que nao sabia :slight_smile:

Obrigadao mesmo.

Abraços

olá,

estava a seguir o exemplo do nosso amigo NiniGodoy e estou qual alguns problemas. Estou a usar o netbeans 7.3, não sei se isso influencia.

O meu código é o seguinte:

[code]
package test_construtor;

public class main {

public static void main(String[] args) {
    //Contar carateres usando o metodo length()
    String testString = "abcdu5B66uD800uDF30";
    int charCount = testString.length();
    System.out.println("caracteres: " + charCount);

    //Contar carateres usando o metodo CodePointCount
    int characterCount = testString.codePointCount(0, charCount);
    System.out.println("Número de caracteres: " + characterCount);

    //Contar carateres usando o metodo getBytes()
    byte[] utf8 = null;
    int byteCount = 0;
    try {
        utf8 = str.getBytes("UTF-8");
        byteCount = utf8.length;
    } catch (UnsupportedEncodingException ex) {
        ex.printStackTrace();
    }



}

}[/code]

Primeiro erro:
avisa que não existe a class str - Qual é a class str? voce criou ou pertence ao java?
Segundo erro:
Em UnsupportedEncodingException - diz “cannot find symbol”

Testei os dois primeiros metodos, length() e codePoinCount() e o resultado é sempre o mesmo!

Resultado:

caracteres: 19
Número de caracteres: 19

valeu

str naquele caso é uma variável do tipo String. Achei que o nome estivesse claro o suficiente.

No seu caso, o codePoint e o length sempre dão iguais pois você só está usando caracteres ascii padrão. Comece a usar caracter chinês ou árabe, e você já vê o número mudar.