Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

nram

Dúvidas em Ficheiros

Recommended Posts

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

Share this post


Link to post
Share on other 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?

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other sites
Localhost

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


here since 2009

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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"].

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other sites
TheDark

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


Desaparecido.

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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).

Share this post


Link to post
Share on other 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!

Share this post


Link to post
Share on other 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).

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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).

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.