Abrir um TXT enorme

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
 
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:
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...
 
Última edição:
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
 
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
 
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/
 
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/

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...
 
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

É 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"
 
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
 
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

isso é capaz de funcionar mas é java e o meu programa está todo em VB6
 
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


;)
 
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


;)

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
 
|[-BooT-]|;2660425 disse:
já agora se me permites a pergunta, porque é que tens essa informação toda num txt?

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... :)
 
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
 
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

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
 
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 ;)
 
pedrotuga, ele está em VB, logo, num sistema Windows
Nesse caso pode usar ActivePerl.

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/i){

de modo a ser case insensitive
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:
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
 
Back
Topo