textdosya yazdırmada out of memory hatası

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
muttalip
Üye
Mesajlar: 71
Kayıt: 18 Haz 2003 08:58
Konum: İstanbul
İletişim:

textdosya yazdırmada out of memory hatası

Mesaj gönderen muttalip »

Aşağıdaki kod ile bir tablonun alan isimlerini ve değerlerini aralarında noktalı virgül olacak şekilde text dosyaya yazdırıyorum.Tabloda çok fazla miktarda kayıt olduğundan yazma işlemi yapılırken text dosya belli bir boyuta ulaştığında out of memory hatası alıyorum ve program kırılıyor. Bu sorunu nasıl halledebiliriz. Yazma işlemi text dosyaya yapıldığı halde bu bellek neden şişiyor. Yanıtlar için şimdiden teşekkürler.
Muttalip TOPTAŞ

Yıldız Teknik Üniversitesi
Bilgi İşlem Dairesi Başkanlığı

Tel: 0212-3832134
Kullanıcı avatarı
Nick_
Üye
Mesajlar: 122
Kayıt: 01 Eki 2007 09:28
Konum: Konya

Re: textdosya yazdırmada out of memory hatası

Mesaj gönderen Nick_ »

Aşağıdaki kod ile bir tablonun ....
Kod?
Bilmemek ayıp değil öğrenmek isteyene öğretmemek ayıp:)
orhancc
Üye
Mesajlar: 585
Kayıt: 24 Ağu 2010 02:14
Konum: İstanbul / Kadıköy
İletişim:

Re: textdosya yazdırmada out of memory hatası

Mesaj gönderen orhancc »

Kod nerede :)
muttalip
Üye
Mesajlar: 71
Kayıt: 18 Haz 2003 08:58
Konum: İstanbul
İletişim:

Re: textdosya yazdırmada out of memory hatası

Mesaj gönderen muttalip »

Pardon kodu unutmuşum

Kod: Tümünü seç

procedure TForm1.Button3Click(Sender: TObject);
var
   dosya:TextFile;
   dosya_isim,baslik_adi:string;
   baslik_say,syc,kaysay,sayac:integer;
   st,st1:String;
begin
   dosya_isim:='c:\persisfb\'+ListBox2.Items[Listbox2.ItemIndex]+'.csv';
   AssignFile(dosya, dosya_isim) ;
   Try
    begin
     if Not FileExists(dosya_isim) Then Rewrite(dosya);
     Append(dosya) ;
     baslik_say:=ListBox1.Items.Count;

     // basliklarin yazdirilmasi
     st:='';
     for syc:=0 to baslik_say-1 do
     begin
        st:=st+ListBox1.Items[syc]+';'
     end;
     st:=st+chr(13)+chr(10);
     WriteLn(dosya,st);
     //BlockWrite(dosya,st,length(st));

     // alan değerlerinin yazdırılması
     IBQuery1.Active:=False;
     IBQuery1.SQL.Clear;
     IBQuery1.SQL.Text:='select count(*) as toplam from '+ListBox2.Items[Listbox2.ItemIndex];
     IBQuery1.Active:=true;
     kaysay:=IBQuery1.FieldByName('toplam').AsInteger;
     IBQuery1.Active:=False;

     ProgressBar1.Max:=kaysay;
     ProgressBar1.Position:=0;

     sayac:=0;
     IBTable1.Active:=True;
     IBTable1.First;
     While Not IBTable1.Eof Do
     begin
       st:='';
       for syc:=0 to baslik_say-1 do
       begin
         baslik_adi:=ListBox1.Items[syc];
         st1:=Trim(ibtable1.fieldbyname(baslik_adi).asstring);
         st1:=AnsiReplaceStr(st1,chr(13)+chr(10),' ');
         st:=st+st1+';'
       end;
       st:=st+chr(13)+chr(10);
     //  BlockWrite(dosya,st,length(st));
       WriteLn(dosya,st);
       ProgressBar1.Position:=ProgressBar1.Position+1;
       sayac:=sayac+1;
       if sayac>100 then
       begin
          sayac:=0;
          CloseFile(dosya);
          AssignFile(dosya, dosya_isim) ;
          Reset(dosya);
          Append(dosya);
       end;

       IBTable1.Next;
     end;
     end;
   finally
     CloseFile(dosya) ;
     IBtable1.Active:=False;
     Ibquery1.active:=False;
     ShowMessage('Aktarma bitti.');
     ProgressBar1.Position:=0;
   end;
end;
Muttalip TOPTAŞ

Yıldız Teknik Üniversitesi
Bilgi İşlem Dairesi Başkanlığı

Tel: 0212-3832134
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3077
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Re: textdosya yazdırmada out of memory hatası

Mesaj gönderen sabanakman »

Bu yöntemle büyük dosyalarda çalışmadım ama büyük metin dosyalarını TStringList sınıfıyla yeterince hızlı bir biçimde oluşturma çalışmalarım olmuştu. Burada dikkat edilmesi gereken en kritik nokta satırlar eklenmeden önce yeterli büyüklükte Capacity özelliğini vermektir. Aksi halde satırlar eklendikçe bellekten yer ayırmaya çalışarak yine hantal bir çalışma yapısı meydana gelecektir.

Kod: Tümünü seç

var Liste:TStringList;
begin
  Liste:=TStringList.Create;
  try
    Liste.SaveToFile(dosya_isim);//izin yetki v.s. gibi engeller varsa hata çıkar ve işlem yapılmaz
    Liste.Capacity:=IBTable.RecordCount+10;//<-bu değer en az doğru olan miktar kadar verilmeli, daha fazla da olabilir :)
....
....
....
    //WriteLn(S); yerine
    Liste.Add(S); //şeklinde satırlar oluşur
....
....
....
    Liste.SaveToFile(dosya_isim);
  finally
    Liste.Free;
  end;
end;
Burada dikkat edilmesi gereken bir diğer nokta ise hedef dosyanın oluşturulabiliyor olmasının gerekliliğidir. Eğer hedef dosya oluşturulamazsa kullanıcı onca zaman boşuna beklemiş olacak ve işlem boşuna yapılmış olacaktır. Bunu engellemek için "Capacity" özelliği ayarlanmadan önce Liste.SaveToFile(dosya_isim); satırı yazılarak gerekli sınama yapılmış olacaktır. Bu kontrol yönteminden farklı yöntem kullanılarak da aynı test yapılabilir ama önerim bu kontrolün başta yapılması olacak. Kolay gelsin.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
muttalip
Üye
Mesajlar: 71
Kayıt: 18 Haz 2003 08:58
Konum: İstanbul
İletişim:

Re: textdosya yazdırmada out of memory hatası

Mesaj gönderen muttalip »

tstringlist yöntemini denedim. Fakat 18000 kayıt yazdıktan sonra out of memory hatasını yine aldım.

Kodu aşağıdaki gibi değiştirdim.

Kod: Tümünü seç

procedure TForm1.Button3Click(Sender: TObject);
var
   dosya:TextFile;
   dosya_isim,baslik_adi:string;
   baslik_say,syc,kaysay,sayac:integer;
   st,st1:String;
   Liste:TStringList;
begin
   dosya_isim:='c:\persisfb\'+ListBox2.Items[Listbox2.ItemIndex]+'.csv';
   //AssignFile(dosya, dosya_isim) ;

   Liste:=TStringList.Create;
   try
    begin
     Liste.SaveToFile(dosya_isim);

    //Try
    // begin
    //  if Not FileExists(dosya_isim) Then Rewrite(dosya);
    //  Append(dosya) ;

     baslik_say:=ListBox1.Items.Count;

     // basliklarin yazdirilmasi
     st:='';
     for syc:=0 to baslik_say-1 do
     begin
        st:=st+ListBox1.Items[syc]+';'
     end;
    // st:=st+chr(13)+chr(10);

     // WriteLn(dosya,st);
     // BlockWrite(dosya,st,length(st));

     // alan değerlerinin yazdırılması
     IBQuery1.Active:=False;
     IBQuery1.SQL.Clear;
     IBQuery1.SQL.Text:='select count(*) as toplam from '+ListBox2.Items[Listbox2.ItemIndex];
     IBQuery1.Active:=true;
     kaysay:=IBQuery1.FieldByName('toplam').AsInteger;
     IBQuery1.Active:=False;

     Liste.Capacity:=kaysay+10;

     Liste.Add(st);
     Liste.SaveToFile(dosya_isim);

     sayac:=0;
     IBTable1.Active:=True;
     IBTable1.First;
     While Not IBTable1.Eof Do
     begin
       st:='';
       for syc:=0 to baslik_say-1 do
       begin
         baslik_adi:=ListBox1.Items[syc];
         st1:=Trim(ibtable1.fieldbyname(baslik_adi).asstring);
         st1:=AnsiReplaceStr(st1,chr(13)+chr(10),' ');
         st:=st+st1+';'
       end;
      // st:=st+chr(13)+chr(10);

       Liste.Add(st);
       //  WriteLn(dosya,st);
       Liste.SaveToFile(dosya_isim);

       IBTable1.Next;
     end;
     end;
   finally
     Liste.Free;
//   CloseFile(dosya) ;
     IBtable1.Active:=False;
     Ibquery1.active:=False;
     ShowMessage('Aktarma bitti.');
   end;
end;

Muttalip TOPTAŞ

Yıldız Teknik Üniversitesi
Bilgi İşlem Dairesi Başkanlığı

Tel: 0212-3832134
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3077
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Re: textdosya yazdırmada out of memory hatası

Mesaj gönderen sabanakman »

InterBase bileşenleri ile alakalı bir durum olabilir mi acep. Kendi çalışmalarımda bundan daha büyük boyutlarda dosyalarda sıkıntı yaşamadım pek.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1316
Kayıt: 07 May 2009 10:42
Konum: İstanbul
İletişim:

Re: textdosya yazdırmada out of memory hatası

Mesaj gönderen SimaWB »

Hatanın kaynağı bu olmayabilir ama en son gönderdiğiniz kodlarda Liste'ye her satır eklediğinizde SaveToFile'ı çağırmanız problem olabilir.

Kod: Tümünü seç

While Not IBTable1.Eof Do
bittikten sonra

Kod: Tümünü seç

Liste.SaveToFile(dosya_isim);
yapılsa yeterli.
There's no place like 127.0.0.1
Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1316
Kayıt: 07 May 2009 10:42
Konum: İstanbul
İletişim:

Re: textdosya yazdırmada out of memory hatası

Mesaj gönderen SimaWB »

Bence sorun FiledByName kaynaklı olabilir. Bundan kurtulmanın 4 farklı yolu var:
http://delphi.about.com/od/database/ss/ ... tabase.htm
There's no place like 127.0.0.1
emin_as
Üye
Mesajlar: 559
Kayıt: 01 Eki 2008 10:05
Konum: izmir
İletişim:

Re: textdosya yazdırmada out of memory hatası

Mesaj gönderen emin_as »

Sanırım ibtable tüm fieldlari ve tüm tabloyu yüklemeye çalışınca yeterli hafıza bulamıyor. IBtable yerine ibsql kullan ve direk olarak textdosyanın arkasına yaz. Gereksiz yere 18.000 kaydı listelerde tutma.

Kod: Tümünü seç

 
procedure Arkaya_Ekle(s:string);
var
  text_dosya : textfile;
begin
  AssignFile(text_dosya,'c:\text.txt');
  Append(text_dosya);
  Writeln(text_dosya,s);
  CloseFile(text_dosya);
end;
Cevapla