Ola Pessoal! Preciso fazer um método que realize a leitura de um arquivo e crie uma tabela de aparições dos caracteres nele contidos. Onde o resultado final é a quantidade de vezes que cada caracter aparece no arquivo.Ate tentei usar a class Map, mas da maneira que preciso ler o arquivo nao consegui.
Alem disso, teria que usar alguma estrutura(vetor, pilha, fila, lista etc), e ordena-los de forma que os caracteres que aparecem mais vezes sejam os primeiros da estrutura!
A leitura eu e a contagem final de caracteres eu ja fiz:
[code]
FileInputStream arquivoFisico = new FileInputStream(“teste.txt”);
BufferedInputStream buffReader = new BufferedInputStream(arquivoFisico);
DataInputStream data = new DataInputStream(buffReader);
int cont =0;
byte vetByte[];
vetByte = new byte[arquivoFisico.available()];
data.read(vetByte);
for (char c : new String(vetByte).toCharArray()) {
System.out.print(c);
cont++;
}
System.out.print("\nQuantidade de caracteres lidos ="+cont);
}
}
[/code]
Entao, como faço para ordena-los e exibir a quantidade de cada caracter?
Você pode usar as classes de java.util (por exemplo, Map, List etc?) O seu problema é bem simples, na verdade.
Há várias coisas que você deve aprender.
Uma delas é que arquivos-texto (é isso que você quer ler, certo) não se lêem todos na memória, nem se lêem com FileInputStream e sim com FileReader.
A segunda é que você precisa usar duas estruturas de dados, não uma só.
Para ler um arquivo caracter por caracter, mas de forma rápida, você pode tentar algo como:
BufferedReader br = new BufferedReader (new FileReader ("teste.txt"));
int intCh;
while ((intCh = br.read()) != -1) {
char ch = (char) intCh;
// tratar aqui o caracter ch
}
br.close();
Você precisa duas estruturas de dados: uma para contar os caracteres - uma sugestão é criar um array de int de 65536 posições, inicializar todas as posições com zero, e então , a cada vez que você achar um caracter, ir incrementando a contagem. Exemplo:
int[] contagem = new int[65536]; // cria um array, já inicializado com zeros
...
contagem[ch] = contagem[ch] + 1;
A outra estrutura, que é a que você está com dificuldades de imaginar, é a que você vai ordenar de acordo com a frequência de cada caracter.
Primeiramente, crie uma classe bem simples:
class Frequencia {
public char ch;
public int freq;
public Frequencia (char ch, int freq) { this.ch = ch; this.freq = freq; }
}
e a seguir, preencha um ArrayList com todas as frequências que não são zero. Ou seja, suponha que o caracter ‘Z’ (código 90) tenha aparecido 4 vezes no seu texto.
Vou supor que o nome desse ArrayList seja frequencias.
Ele deve aparecer naquele array contagem como:
contagem [90] tem o valor 4
Então você adiciona ao arraylist de Frequencia um objeto Frequencia (ou seja, frequencias.add (new Frequencia(90, 4)).
Se o caracter ‘y’ (código 121) não apareceu nenhuma vez, o valor de contagem [121] vai ser zero, então você não adiciona ao ArrayList nenhum objeto Frequencia.
Por último, você ordena, usando Collections.sort, o ArrayList de forma decrescente. Uma forma de fazer isso seria:
Collections.sort (frequencias, new Comparator<Frequencia>() {
public int compare (Frequencia f1, Frequencia f2) {
if (f1.freq > f2.freq) return -1;
else if (f1.freq < f2.freq) return +1;
else return 0;
}
);
Mto obrigada pela ajuda, isso esclareceu um pouco e consegui fazer a primeira parte. Agora preciso fazer a Codificação e gravação do arquivo com base nessa tabela de huffman e a Leitura, decodificação e gravação do arquivo descompactado. Tava dando uma pesquisada nos foruns e , cheguei a testar um exemplo como esse, usando LZW:
import java.io.*;
class LZW {
public static void main (String[] args) throws IOException {
if (!args[0].equals("")){
comprime(args[0]);
descomprime("output.dat");
}
}
private static void comprime (String nomearq) {
int atual, cont;
String[] dicionario = new String[65536];
for (cont = 0; cont < 256; cont++)
dicionario[cont] = "" + (char) cont;
try {
FileReader fr = new FileReader(nomearq);
FileOutputStream tw = new FileOutputStream("output.dat");
DataOutputStream fw = new DataOutputStream(tw);
String str = "";
int last = 0;
while ((atual = fr.read()) != -1) {
str += "" + (char) atual;
boolean adiciona = true;
for (int i = 0; i < cont; i++) {
if (dicionario[i].equals(str)) {
adiciona = false;
last = i;
}
}
if (adiciona) {
fw.writeByte((byte) (last / 256)); fw.writeByte((byte) (last % 256));
fw.writeByte((byte) atual);
if (cont >= 65536)
cont = 0;
dicionario[cont] = str;
cont++;
str = "";
last = 0;
}
}
fw.writeByte((byte) -1);
fr.close(); fw.close(); tw.close();
System.out.println("Arquivo de texto comprimido para output.dat");
} catch (FileNotFoundException fnfE) {
System.out.println("Arquivo nao encontrado.");
} catch (IOException IOE) {
System.out.println("Excecao IO.");
}
}
Mas teria que fazer isso usando a classe bitset para “montar” os bits do arquivo a partir da tabela de huffman.
Agora como posso juntar todos estes binários em ordem de acordo com o texto para salvar em um arquivo compactado?
Por exemplo:
T e s t a n d o = 11001 11011 10110 0100 111 100 11010 1010
Testando = 1100111011101100100111100110101010