EDBClient - Insufficiente memory for this operation

23/09/2021

0

Pessoal, estou com um projetinho de teste aqui onde uma das tarefas é resolver um problema de memória que ocorre com armazenamento de arquivos utilizando ClientDataSet.

O objetivo é armazenar 100 (ou mais) arquivos PDF que possuem em média 47MB cada um. Cada arquivo será um registro do ClientDataSet.

for i := 1 to 100 do
begin
    cds.Append;
    TBlobField(cds.FieldByName('arquivo')).LoadFromFile(sCaminhoDoArquivo);
    cds.Post;
end;


Com o código acima, lá pela metade do processo estoura o erro "EDBClient - Insufficiente memory for this operation".

Já revirei a internet toda e não achei uma solução. =/
Prophet

Prophet

Responder

Posts

23/09/2021

Emerson Nascimento

// coloque uma instrução que leia a tabela porem não retorne registros.
// por exemplo: tua tabela tem um campo ID que inicia em 1.
// coloque a seguinte instrução no ClientDataset:
// "SELECT * FROM TABELA WHERE ID = -1" sabendo que nenhum registro atenderá à condição
// ou seja, sempre que o ClientDataset for aberto, ele não trará registros
// daí você faz a iteração sempre fechando e abrindo o ClientDataset, de
// modo que tenha apenas 1 registro na memória, evitando o estouro.
for i := 1 to 100 do
begin
    if cds.Active then cds.Close; // fecha o dataset (e libera memória)
    cds.Open; // abre o dataset sem registros, visto que a instrução SQL está preparada para isto

    cds.Append; // insere um registro na posição do ponteiro
    TBlobField(cds.FieldByName('arquivo')).LoadFromFile(sCaminhoDoArquivo); // atribui o arquivo ao campo
    cds.Post; // grava o conteúdo do dataset
    cds.ApplyUpdates(0); // descarrega o conteúdo no banco de dados
end;

Responder

24/09/2021

Prophet

// coloque uma instrução que leia a tabela porem não retorne registros.
// por exemplo: tua tabela tem um campo ID que inicia em 1.
// coloque a seguinte instrução no ClientDataset:
// "SELECT * FROM TABELA WHERE ID = -1" sabendo que nenhum registro atenderá à condição
// ou seja, sempre que o ClientDataset for aberto, ele não trará registros
// daí você faz a iteração sempre fechando e abrindo o ClientDataset, de
// modo que tenha apenas 1 registro na memória, evitando o estouro.
for i := 1 to 100 do
begin
    if cds.Active then cds.Close; // fecha o dataset (e libera memória)
    cds.Open; // abre o dataset sem registros, visto que a instrução SQL está preparada para isto

    cds.Append; // insere um registro na posição do ponteiro
    TBlobField(cds.FieldByName('arquivo')).LoadFromFile(sCaminhoDoArquivo); // atribui o arquivo ao campo
    cds.Post; // grava o conteúdo do dataset
    cds.ApplyUpdates(0); // descarrega o conteúdo no banco de dados
end;



Obrigado pela resposta, mas não resolveu =/
O problema é que não estou trabalhando com banco de dados. O objetivo do ClientDataSet é só armazenar os arquivos em memória (no caso, 100 arquivos) e depois é chamado um método que vai iterar sobre esse ClientDataSet e salvar cada arquivo num diretório específico.

Ele nem chega a entrar no método de salvar porque no meio do processo de alimentar o ClientDataSet dá o estouro de memória.
Responder

24/09/2021

Emerson Nascimento

a lógica deveria ser a mesma.
você precisa esperar dar carga em 100 arquivos?
porque não pode fazer a gravação a cada leitura?
for i := 1 to 100 do
begin
    if cds.Active then cds.Close; // fecha o dataset (e libera memória)
    cds.CreateDataset;
 
    cds.Insert; // insere um novo registro
    TBlobField(cds.FieldByName('arquivo')).LoadFromFile(sCaminhoDoArquivo); // atribui o arquivo ao campo
    cds.Post; // grava o conteúdo do dataset

    // grava o arquivo na pasta desejada
    [...]
end;
Responder

24/09/2021

Prophet

a lógica deveria ser a mesma.
você precisa esperar dar carga em 100 arquivos?
porque não pode fazer a gravação a cada leitura?
for i := 1 to 100 do
begin
    if cds.Active then cds.Close; // fecha o dataset (e libera memória)
    cds.CreateDataset;
 
    cds.Insert; // insere um novo registro
    TBlobField(cds.FieldByName('arquivo')).LoadFromFile(sCaminhoDoArquivo); // atribui o arquivo ao campo
    cds.Post; // grava o conteúdo do dataset

    // grava o arquivo na pasta desejada
    [...]
end;


Sim, entendo que existem N formas de fazer isso. Só que se eu tivesse que manter essa estrutura de primeiro carregar os 100 arquivos no ClientDataSet e só depois salvá-los num diretório, você enxerga alguma solução para evitar esse estouro de memória?
Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar