Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

nram

Dúvidas em Ficheiros

Mensagens Recomendadas

nram

Boas!

Preciso de guardar os dados em ficheiros, e fazer mais algumas coisas.

Quanto ao escrever e guardar. Tudo bem, o maior problema é quando se tem que editar ou apagar algumas linhas.

Imaginando que tenho X linhas, e quero editar 5 linhas, imaginando com que existe 10Caracteres. Como posso eu editar esses caracteres? (imaginando que agora só pretendo introduzir 2 ou 3? Existe maneira?

E se por exemplo pretendo apagar 4 linhas? (como iria eu limpar esses 10caracteres?) ... :S

O objectivo é que não fosse necessário copiar o ficheiro para outro sítio, e voltar copiar o pretendido, visto que irão ser milhares de linhas.

Cumprimentos

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nram

Já conheço o FSEEK. Eu queria saber, era como apagar ou editar... ou seja, desaparecer do ficheiro...

é que editar quando tem o mesmo número de caracteres é fácil, mas quando não tem como vou fazer?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
TheDark

Depende da maneira como interpretas o ficheiro. Se ignorares linhas em branco, ou caracteres nulos, e o que pretendes escrever for menor do que o que pretendes apagar, podes inserir caracteres nulos ou linhas em branco.

Se caracteres nulos ou linhas em branco forem valores válidos, tens que reescrever tudo o que estiver para a frente do que queres eliminar.


Desaparecido.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Localhost

Se calhar é melhor ler para uma string, trabalhar com ela "dentro" do programa e depois metê-la outra vez no ficheiro, já modificada.


here since 2009

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
TheDark

Para evitar a cópia de ficheiros, esse seria o caminho a seguir. No entanto, se os ficheiros forem demasiado grandes, isso pode não ser exequível por limitações de memória, e nesse caso criar um novo ficheiro, copiar para lá o conteúdo alterado do ficheiro antigo, apagar o ficheiro antigo e renomear o novo será a melhor estratégia.


Desaparecido.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Localhost

Sim, tens razão. No entanto, pode só copiar as strings que pretende editar. É muito melhor trabalhar com elas indoor  :P


here since 2009

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nram

Para evitar a cópia de ficheiros, esse seria o caminho a seguir. No entanto, se os ficheiros forem demasiado grandes, isso pode não ser exequível por limitações de memória, e nesse caso criar um novo ficheiro, copiar para lá o conteúdo alterado do ficheiro antigo, apagar o ficheiro antigo e renomear o novo será a melhor estratégia.

Podes-me dizer como se renomeia ficheiros?

PS: obrigado, pelos esclarecimentos.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
TheDark

Sim, tens razão. No entanto, pode só copiar as strings que pretende editar. É muito melhor trabalhar com elas indoor  :P

Sem utilizar um ficheiro extra? E como é que ele ia editar as strings se não as copiasse para a memória?


Desaparecido.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Localhost

Eu disse precisamente isso. Copia para "dentro" do programa e depois edita-as, não falei em ficheiro extra.


here since 2009

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
TheDark

Continuo a não perceber como é que ele poderia trabalhar as strings que quer editar sem as copiar para a memória :)

Porque se

É muito melhor trabalhar com elas indoor

deve haver outra maneira...


Desaparecido.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nram

Continuo a não perceber como é que ele poderia trabalhar as strings que quer editar sem as copiar para a memória :)

Porque se

deve haver outra maneira...

Penso que se devem estar a referir caracter a caracter! [Continuando na mesma ser "indor"].

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Localhost

Continuo a não perceber como é que ele poderia trabalhar as strings que quer editar sem as copiar para a memória ;)

Porque se

deve haver outra maneira...

Eu é que se calhar ainda não entendi o que queres dizer em copiar para a memória.


here since 2009

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
TheDark

"Copiar para a memória", "trabalhar com ela "dentro" do programa" e "trabalhar com elas "indoor"" deveriam ser sinónimos.


Desaparecido.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Localhost

Eu disse precisamente isso. Copia para "dentro" do programa e depois edita-as, não falei em ficheiro extra.

E foi isso que eu disse, como podes ver.

Estou a ficar confuso xD


here since 2009

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Cynary

Abres o ficheiro para edição.

Tens no programa a string nova, o seu comprimento, a posição da string antiga (a que se vai apagar), e o seu comprimento.

Coloca o ficheiro na posição da string antiga.

Se o comprimento da string nova for maior que o comprimento da string antiga, move todos os caracteres do ficheiro a partir do fim da string antiga (posição+comprimento) x posições para a frente (x = comprimento da nova - comprimento da antiga).

Se o comprimento da string nova for menor que o comprimento da string antiga escreves a string nova a partir da posição da string antiga e moves todos os caracteres do ficheiro, x posições para trás (x = comprimento da antiga - comprimento da nova).

Para mover os caracteres, podes fazê-lo um a um.

Assim, nem precisas de carregar o conteúdo do ficheiro na memória.

Claro que, se souberes de antemão que o tamanho do ficheiro tem um máximo razoável para ser completamente colocado na memória, convém leres todo o seu conteúdo para uma string, fechares o ficheiro e abrires novamente, de forma a reescrevê-lo, editas a string na memória com as funções standard e escreves a string novamente no ficheiro.

(peço desculpa se a minha resposta estiver confusa, mas já é tarde e estou a ficar com sono, e quando isso acontece, as minhas frases começam a perder estrutura xD).

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nram

Abres o ficheiro para edição.

Tens no programa a string nova, o seu comprimento, a posição da string antiga (a que se vai apagar), e o seu comprimento.

Coloca o ficheiro na posição da string antiga.

Se o comprimento da string nova for maior que o comprimento da string antiga, move todos os caracteres do ficheiro a partir do fim da string antiga (posição+comprimento) x posições para a frente (x = comprimento da nova - comprimento da antiga).

Se o comprimento da string nova for menor que o comprimento da string antiga escreves a string nova a partir da posição da string antiga e moves todos os caracteres do ficheiro, x posições para trás (x = comprimento da antiga - comprimento da nova).

Para mover os caracteres, podes fazê-lo um a um.

Assim, nem precisas de carregar o conteúdo do ficheiro na memória.

Claro que, se souberes de antemão que o tamanho do ficheiro tem um máximo razoável para ser completamente colocado na memória, convém leres todo o seu conteúdo para uma string, fechares o ficheiro e abrires novamente, de forma a reescrevê-lo, editas a string na memória com as funções standard e escreves a string novamente no ficheiro.

(peço desculpa se a minha resposta estiver confusa, mas já é tarde e estou a ficar com sono, e quando isso acontece, as minhas frases começam a perder estrutura xD).

Só uma coisa, não me lembro da função que mete o ficheiro todo numa string. :S ...

Imaginando que eu não sei quantos caracteres tem o ficheiro!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Cynary

Crias uma string com um número de caraceteres superior ao máximo do ficheiro, e usas a função fgets, em que especificas os caracteres a ler como sendo o máximo da string. A fgets pára ao chegar a uma nova linha ou EOF, por isso vais repetindo até chegares a EOF (devolve EOF).

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nram

Crias uma string com um número de caraceteres superior ao máximo do ficheiro, e usas a função fgets, em que especificas os caracteres a ler como sendo o máximo da string. A fgets pára ao chegar a uma nova linha ou EOF, por isso vais repetindo até chegares a EOF (devolve EOF).

Pois, mas isso não dá no meu caso! Posso ter milhares, como apenas 1! XD

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Cynary

Pois, mas isso não dá no meu caso! Posso ter milhares, como apenas 1! XD

Se tens um máximo, coloca esse máximo+1 (terminador da string) num vector de caracteres. Depois lê esse máximo. Se tiveres só um, a fgets vai ler apenas um e terminar com EOF. Se tiveres milhares, vais repetindo até EOF. A fgets não lê além de \n ou EOF.

Se não tens máximo, altera caractér a caractér, nunca colocando todo o conteúdo do ficheiro na memória (podes usar o processo que descrevi anteriormente).

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
TheDark

Se o comprimento da string nova for maior que o comprimento da string antiga, move todos os caracteres do ficheiro a partir do fim da string antiga (posição+comprimento) x posições para a frente (x = comprimento da nova - comprimento da antiga).

Se o comprimento da string nova for menor que o comprimento da string antiga escreves a string nova a partir da posição da string antiga e moves todos os caracteres do ficheiro, x posições para trás (x = comprimento da antiga - comprimento da nova).

Para mover os caracteres, podes fazê-lo um a um.

Assim, nem precisas de carregar o conteúdo do ficheiro na memória.

Eh pá... não sabendo qual o tamanho máximo do ficheiro, já viste bem o que estás a sugerir? Imagina que ele tem um ficheiro de 50MB e quer alterar a linha 5, a 8, a 11 e a 18 (números aleatórios ;) ), e que para a frente da linha 18 ficam 48MB. Vai estar a reescrever 48MB 4 vezes. Agora imagina que em vez de 50MB, são 500MB, e que em vez de 4 linhas quer alterar 25. Não é grande ideia estar a reescrever 400MB no disco 25 vezes (imaginando que é este o tamanho do ficheiro após a última linha alterada, e desprezando as linhas anteriores a isso).

Mais uma vez, estou a extrapolar porque não se sabe o tamanho dos ficheiros.

Já para não falar em mover os caracteres um a um... e o conteúdo do ficheiro vai SEMPRE passar pela memória, mesmo que seja um caracter de cada vez ;) Era essa a discussão que eu estava a ter com o Localhost (se bem que, na realidade, estava era a discutir comigo próprio ::) ), por causa desta frase:

É muito melhor trabalhar com elas indoor  B)

Mais uma vez: se é "melhor" trabalhar com elas "indoor", qual é o método (que é pior) para se trabalhar com elas sem ser "indoor"? B)

De qualquer forma, a minha sugestão anterior (ler cada linha do ficheiro original, modificá-la ou não, escrever num ficheiro novo, e no fim apagar o original e renomear o novo) é muito mais eficiente que a sugerida pelo Cynary, se tiveres espaço suficiente para ter duas vezes o ficheiro no disco, temporariamente. Além de que é mais simples de implementar.


Desaparecido.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nram

Se tens um máximo, coloca esse máximo+1 (terminador da string) num vector de caracteres. Depois lê esse máximo. Se tiveres só um, a fgets vai ler apenas um e terminar com EOF. Se tiveres milhares, vais repetindo até EOF. A fgets não lê além de \n ou EOF.

Se não tens máximo, altera caractér a caractér, nunca colocando todo o conteúdo do ficheiro na memória (podes usar o processo que descrevi anteriormente).

Está certo, eu de manhã estava mesmo a dormir! Enfim.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Cynary

Eh pá... não sabendo qual o tamanho máximo do ficheiro, já viste bem o que estás a sugerir? Imagina que ele tem um ficheiro de 50MB e quer alterar a linha 5, a 8, a 11 e a 18 (números aleatórios ;) ), e que para a frente da linha 18 ficam 48MB. Vai estar a reescrever 48MB 4 vezes. Agora imagina que em vez de 50MB, são 500MB, e que em vez de 4 linhas quer alterar 25. Não é grande ideia estar a reescrever 400MB no disco 25 vezes (imaginando que é este o tamanho do ficheiro após a última linha alterada, e desprezando as linhas anteriores a isso).

Mais uma vez, estou a extrapolar porque não se sabe o tamanho dos ficheiros.

Já para não falar em mover os caracteres um a um... e o conteúdo do ficheiro vai SEMPRE passar pela memória, mesmo que seja um caracter de cada vez ;) Era essa a discussão que eu estava a ter com o Localhost (se bem que, na realidade, estava era a discutir comigo próprio :B) ), por causa desta frase:

Mais uma vez: se é "melhor" trabalhar com elas "indoor", qual é o método (que é pior) para se trabalhar com elas sem ser "indoor"? B)

De qualquer forma, a minha sugestão anterior (ler cada linha do ficheiro original, modificá-la ou não, escrever num ficheiro novo, e no fim apagar o original e renomear o novo) é muito mais eficiente que a sugerida pelo Cynary, se tiveres espaço suficiente para ter duas vezes o ficheiro no disco, temporariamente. Além de que é mais simples de implementar.

Pois o problema da tua ideia é que pode ultrapassar o espaço em disco e o meu método permite que se façam várias alterações no ficheiro escrevendo-se apenas uma vez no disco (é só calcular a diferença de posições dos caracteres revelantes e mudà-los. Além disso só precisamos de alterar os caracteres a partir da primeira alteração até ao fim do ficheiro e não necessita de usar o ficheiro todo).

Outra observação: os teus argumentos só funcionam quando todas as alterações são conhecidas de antemão mas quando se quer uma de cada vez, é mais lento copiar tudo de cada vez ainda por cima porque os discos são normalmente lentos.

Quando se fala em trabalhar indoor significa ter o ficheiro todo na memória. Podes manipular a string mas não caracter a caracter, sem sair da memória.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.