1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

Abrir um TXT enorme

Discussão em 'Programação' iniciada por droidman, 10 de Março de 2008. (Respostas: 28; Visualizações: 1963)

  1. droidman

    droidman Power Member

    Alguem sabe alguma maneira de procurar dentro de um TXT de grandes dimensões algum tipo de string sem ter de o abrir completamente?
    Por exemplo, um ficheiro de 200mb em txt com milhões de strings, e quero procurar uma, em vez de carregar essa string toda para a memória e por o pc atafulhado de palha, e caso a string exista ele mostra o resultado completo da linha onde ela se encontra.
    A ideia era fazer isto em VB6
    agradecia qualquer ajuda
     
  2. rj.rodrigues

    rj.rodrigues Power Member

    Ora bem, isto é um pseudo-codigo, com algumas semelhanças com o java.

    Código:
    boolean procurarString(File file, String s){
     char[] chave = s.toChar();
     boolean encontrou = false;
     char c = '\0';
     do{
       if(c!=chave[0]){
         c = toChar(file.readByte());
       }
       int i;
       for(i=0; i<chave.length && chave[i]==c; i++){
         c = toChar(file.readByte());
       }
       if(i==chave.length){
         encontrou=true;
       }
     }while(c!=File.eof() && !encontrou);
    }
    
     
    Última edição: 11 de Março de 2008
  3. droidman

    droidman Power Member

    ele assim precorre todo o ficheiro limpando a variavel constantemente, talvez seja rapido mas nem vejo se da para melhorar... vou testar
    ja agora, como é que uma base de dados procura um campo ? ha bases de dados com gigas e os dados são encontrados muito rápidamente...
     
  4. rj.rodrigues

    rj.rodrigues Power Member

    Última edição: 11 de Março de 2008
  5. Kayvlim

    Kayvlim Undefined Moderator
    Staff Member

    Os dados estão indexados. Não tens esse controlo no plain text ;)
    Quanto ao que queres, a forma mais simples que me parece ser é a mais básica de todas
    Código:
    open ficheiro for input as #1
      do until eof(1)
        line input #1, buffer
        if instr(buffer, procurar) then
          msgbox buffer
        end if
      loop
    close #1
    
    (escrito à mão sem testar, mas deve funcionar)

    Não serve? Há formas mais rápidas, mas envolvem APIs que nem eu entendo :x
     
  6. droidman

    droidman Power Member

    sim angelofwisdom eu vou usar isto parece-me ser a forma mais rápida e fácil.
    uma vez encontrei o metodo mais incrivel foi o REPLACE e era muito rapido. usei para apagar repetidos num ficheiro de dimensões assusatdoras, usava algo do genero, if string = X then replace x era mais ou menos isto, numa textbox, ou seja, toda a string igual aquilo era apagada, o problema é que as vezes ele apagava letras por serem iguais, tem de ser mesmo strings exatas. o replace tambem é bom para apagar paragrafos de ficheiros onde nao pode haver qualquer tipo de paragrafo. tenha que tamanho ele tiver. O problema sao as limitações de memoria impostas pelo Vb6 às textboxes e listboxes
     
  7. reise

    reise Power Member

    Se tem de ser programado lê blocks de dados de cada vez, nunca byte a byte, nunca.
    Se só queres procurar a palavra arranja uma máquina unix e faz: cat ficheiro.txt | grep PALAVRA. Se só tiveres windows vai aqui http://www.wingrep.com/
     
  8. droidman

    droidman Power Member

    o programa é para correr em windows, embora para mim eu tenha ubuntu no portatil aqui ao lado.

    Já agora, o código que me deram, procura em case sensitive? era pena...
     
  9. droidman

    droidman Power Member

    É case sensitive! :(
    ha alguma forma de dar a volta a isto em VB ? eu quero que ele encontre resultados tanto para strings como "CARLOS" como "carlos" ou "CaRLoS"
     
  10. reise

    reise Power Member

    Código:
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class ReadText {
    
        public static void main(String[] args) throws IOException {
            try {
                BufferedReader in = new BufferedReader(new FileReader(args[0]));
                String str;
                while ((str = in.readLine()) != null) {
                    if (str.toUpperCase().contains(args[1].toUpperCase())) {
                        System.out.println("Encontrou:"+str);
                    }
                }
                in.close();
            } catch (IOException e) {
            }
        }
    }
    Lê linha a linha e não olha ao case.
    primeiro parametro é o nome do ficheiro o segundo é a palavra a procurar
     
  11. droidman

    droidman Power Member

    isso é capaz de funcionar mas é java e o meu programa está todo em VB6
     
  12. Kayvlim

    Kayvlim Undefined Moderator
    Staff Member

    Se olhares para o código dele, ele faz o que eu te ia aconselhar agora: comparar as strings em MAIÚSCULAS :)

    Ou seja, para ser case-insensitive, troca
    Código:
    if instr(buffer, procurar) then
    por
    Código:
    if instr(ucase(buffer), ucase(procurar)) then

    ;)
     
  13. droidman

    droidman Power Member

    funciona na perfeição, meti uma checkbox para case sensitive e pesquizas não case sensitive. o programa neste momento verifica se ha strings iguais ás inseridas numa textbox num ficheiro que tenho com 7.8 milhões de strings (aprox 370mb em txt) em 35 a 40 segundos num core 2 duo 2.13ghz
     
  14. |[-BooT-]|

    |[-BooT-]| Folding Member

    já agora se me permites a pergunta, porque é que tens essa informação toda num txt?
     
  15. droidman

    droidman Power Member

    a principio fiz um programa parecido com este para um amigo que eliminava e-mails repetidos de ficheiros em TXT que ele extraia do servidor de mails dele e depois é que me disse k o fazia assim, ele nao sabia que ao fazer o dump do SQL bastava por lá que so queria resultados unicos mas pronto tive imenso trabalho mas ao menos aprendi.
    Este programa tou a usa-lo para encontrar chaves MD5 em ficheiros txt grandes...
    Tem algumas funcionalidades... :)
     
  16. pedrotuga

    pedrotuga Power Member

    Tipo, o grep faz precisamente isso.

    Se usas um sistema operativo baseado em unix ( linux, bsd, macos, etc ) abre uma linha de comandos e..

    Código:
    man grep
    Se fores utilizador do windows tens que instalar o grep. Google -> grep windows

    Se for para um trabalho académico, podes abrir o ficheiro linha a linha ou caracter a caracter, isso é perfeitamente possivel em praticamente todas as linguagens.
    No teu caso dá-te jeito ser linha a linha.

    Em perl é particularmente facil de fazer isso.

    Código:
    $FICHEIRO = "grandeficheiro.txt";
    open(FICHEIRO) or die("Could not open log file.");
    $atuastring = "qq coisa a procurar aqui";
    $i=1;
    foreach $line (<FICHEIRO>) {
        chomp($line);              # remove the newline from $line.
        
        if ($line =~ /$atuastring/){
            print "Linha ".$i.":".$line;
        }
        $i++;
    }
    Não testei este código mas deve funcionar
     
  17. droidman

    droidman Power Member

    por acaso procurei um bocado e nao encontrei como por isto em vb. nem sei como carregar o grep, talvez seja por componenete, n sei bem, nao o encontro nos componentes
     
  18. Kayvlim

    Kayvlim Undefined Moderator
    Staff Member

    pedrotuga, ele está em VB, logo, num sistema Windows ;)
    Já agora, quanto ao teu código em Perl, para a tua regexp resultar, em vez de
    Código:
    if ($line =~ /$atuastring/){
    devias era ter algo como
    Código:
    if ($line =~ /$atuastring/[B]i[/B]){
    de modo a ser case insensitive ;)
     
  19. slack_guy

    slack_guy Power Member

    Nesse caso pode usar ActivePerl.

    Em boa verdade, até podia escrever assim:
    Código:
    #!/usr/bin/perl 
    use strict;
    use warnings;
    my $f = q|/path/to/file|;
    my $str = q|string|;
    open my $F,'<',$f or die "$!\n";
    while (<$F>) { printf "%.8d %s", $., $_ if /$str/im; }
    close $F;
    
    Aliás, como se trata de Perl, até podia escrever de muitas outras formas :-)
     
    Última edição: 13 de Março de 2008
  20. droidman

    droidman Power Member

    bem a ideia era isto ficar incluido no meu software em GUI e nao linha de comandos pk o programa vai ser usado por pessoas que percebem pouco... de qualquer forma ele ja funciona está a ler cerca de 200mb a cada 35 a 40 segundos e está feito em VB6 nao me parece uma média muito acima dos valores que eu pretendia. cada ficheiro de 150mb tem aproximadamente 7 milhões de linhas. apenas fica a minha duvida, se ha outra forma de eu incorporar os dados sem ser num txt e sim num tipo de ficheiro que agora nao me venha à memória e que acelere isto
     

Partilhar esta Página