bu döngüde sorun nerede ?

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
seci20

bu döngüde sorun nerede ?

Mesaj gönderen seci20 »

ustalarım merhaba uzun suredır ustunde calıstıgım bır kod var.Kod telefona veri gondermek ıcın kullanılıyor.Kodun pythonla yazılmıs halı var yanlız sanırsam dongude bır hata yapyorum verıyı yarım gonderıp donguyu tamamlıyor uzun suredır ugrastım ama malasef başarılı olamadım.Kodun pythonla yazılmıs halı şu.

Python

Kod: Tümünü seç

def write_partition(comm, disk_fd, local_path, part_offset, part_size):
    write_offset = BLOCK_SIZE * (part_offset // BLOCK_SIZE)
    end_offset = part_offset + part_size
    # TODO support unaligned writes via read/modify/write
    if part_offset % BLOCK_SIZE:
        raise RuntimeError("Unaligned partition writes are not supported yet")

    # Sanity check
    assert part_offset >= 34 * 512, "Will not allow overwriting GPT scheme"

    with open_local_readable(local_path) as f:
        try:
            length = f.seek(0, 2)
        except OSError:
            # Will try to write up to the end of the file.
            _logger.debug("File %s is not seekable, length is unknown",
                    local_path)
        else:
            # Restore position and check if file is small enough
            f.seek(0)
            if length > part_size:
                raise RuntimeError("File size %d is larger than partition "
                        "size %d" % (length, part_size))
            # Some special bytes report 0 (such as /dev/zero)
            if length > 0:
                _logger.debug("Will write %d bytes", length)
        written = 0
        while write_offset < end_offset:
            chunksize = min(end_offset - write_offset, BLOCK_SIZE * MAX_BLOCK_SIZE)
            data = f.read(chunksize)
            if not data:
                break # End of file
            laf_write(comm, disk_fd, write_offset // BLOCK_SIZE, data)
            written += len(data)
            write_offset += chunksize
            if len(data) != chunksize:
                break # Short read, end of file
        _logger.info("Done after writing %d bytes from %s", written, local_path)

benim yazdığım kod ise şu...

Kod: Tümünü seç

var
  TmpBuf,DatBuf:TMyByteArray;
MAX_BLOCK_SIZE,BLOCK_SIZE,part_offset,write_offset,end_offset,chunksize,Maxval,RdLen:integer;
begin
MAX_BLOCK_SIZE:=(16 * 1024 - 512) div 512;
BLOCK_SIZE:=512;
Strm:=TFileStream.Create('recovery',fmOpenRead + fmShareDenyNone);
  FullDatLen:=Strm.Size;
  Strm.Seek(0,soFromBeginning);
  strm.Position:=0;
 part_offset:=34 * 512;
write_offset:= BLOCK_SIZE * (part_offset div BLOCK_SIZE);
end_offset:=FullDatLen+part_offset;
 chunksize := min(FullDatLen - write_offset, BLOCK_SIZE * MAX_BLOCK_SIZE);
 Maxval:= MAX_BLOCK_SIZE div chunksize;
    for i:= 0 to Maxval -1 do
    begin
 SetLength(DatBuf,ChunkSize);
      SetLength(TmpBuf,ChunkSize);
      RdLen:=Strm.Read(DatBuf[0],ChunkSize);
      CopyMemory(@TmpBuf[0],@DatBuf[0],Length(DatBuf));
OpenComPort1('COM6',115200);
WriteComPort(TmpBuf,Length(TmpBuf),8,5000,10);
delay(100);
DatBuf[0]:=DatBuf[0]+chunksize;
Application.ProcessMessages;
end;
veriyi gondermeye başlıyor ama yarım gonderıp donguyu tamamlıyor bır türlü düzgün bir döngü yapmayı başaramadım nerede hata yapıyor olabılırım ?
ertank
Kıdemli Üye
Mesajlar: 1716
Kayıt: 12 Eyl 2015 12:45

Re: bu döngüde sorun nerede ?

Mesaj gönderen ertank »

Merhaba,

Kodu tam anlayamadım. Dosya boyutunu 70000 byte varsayalım. Bu durumda yanlış hesap yapmadı isem aşağıdaki değerler gerçekleşecektir.

MAX_BLOCK_SIZE = 31
BLOCK_SIZE:=512
part_offset:=17408
write_offset:= 17408
end_offset:= 87408
chunksize := 15872
Maxval:= 31 div 15872 sonucundan 0 (sıfır olacaktır)
for döngüsüne hiç girmeyecektir. Yani normalde hiç veri göndermemesi gerekecektir.

Biraz daha detay bilgi vermeniz mümkün mü acaba?
seci20

Re: bu döngüde sorun nerede ?

Mesaj gönderen seci20 »

ertank yazdı:Merhaba,

Kodu tam anlayamadım. Dosya boyutunu 70000 byte varsayalım. Bu durumda yanlış hesap yapmadı isem aşağıdaki değerler gerçekleşecektir.

MAX_BLOCK_SIZE = 31
BLOCK_SIZE:=512
part_offset:=17408
write_offset:= 17408
end_offset:= 87408
chunksize := 15872
Maxval:= 31 div 15872 sonucundan 0 (sıfır olacaktır)
for döngüsüne hiç girmeyecektir. Yani normalde hiç veri göndermemesi gerekecektir.

Biraz daha detay bilgi vermeniz mümkün mü acaba?
hocam ılk oncelıkle cevap verdıgınız ıcın cok tesekkur ederım...dosya boyutu tam olarak 22.528 kb yanı 23068.672 byte bu ben onu bir deneme sırasında yaptım yanı tam olarak ne alıcam onu bır turlu bulamadım ne aldıysam hep yarım verı gonderıyor...Yanı aslında yukarda yapılan 512 kb aralıklarla dosyayı gondermek ama ben basaramadım bır turlu...
ertank
Kıdemli Üye
Mesajlar: 1716
Kayıt: 12 Eyl 2015 12:45

Re: bu döngüde sorun nerede ?

Mesaj gönderen ertank »

Aşağıdaki linkte hazır bir kod var. Bu kod ile örneğin bir dosyanın 5nci 512kb kısmını okuman mümkün. Dosyada kaç 512kb bölüm olduğunu dosya boyutunu 512'ye bölerek bulabilirsin. Döngünü buna göre kurabilirsin.

Ancak, sen TMyByteArray tipinde bir veriyi seri port'a gönderiyorsun. Benim aşağıda verdiğim örnek link ise TMemoryStrem kullanıyor. Senin de TMemoryStream kullanman mümkün olursa bu kodu kullanabilirsin.

Zira senin kodunu ben net bir şekilde anlayamadım.

http://stackoverflow.com/questions/2707 ... nto-stream

bahsi geçen kod:

Kod: Tümünü seç

procedure readFileChunk(FileName: string; var MS: TMemoryStream; ChunkNo: Integer; ChunkSize: Int64);
var fs: TFileStream;
begin
  fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  if ChunkSize * (ChunkNo-1) <= fs.Size then
  begin
    fs.Position := ChunkSize * (ChunkNo-1);
    if fs.Position + ChunkSize <= fs.Size then
      ms.CopyFrom(fs, ChunkSize)
    else
      ms.CopyFrom(fs, fs.Size - fs.Position);
  end
  else
    MessageBox(Form2.WindowHandle, 'File does not have so many chunks', 'WARNING!', MB_OK);
  fs.Free;
end;
kullanım şekli:

Kod: Tümünü seç

readFileChunk(FileName,MemoryStream,ChunkNumber,ChunkSize);
Olası dosyayı parça parça okuyan kod örneği. (Test edilmemiştir):

Kod: Tümünü seç

const
  OkumaBuyuklugu = 512 * 1024;
var
  DosyaAdi: string;
  FileSizeInBytes, BolumSayisi: Integer;
  MyStream: TMemoryStream;
  StreamInString: string;
begin
  DosyaAdi := 'c:\okunacak\dosya.bin';
  FileSizeInBytes := FileSize(DosyaAdi);
  BolumSayisi := FileSizeInBytes div OkumaBuyuklugu;
  // Eger dosya boyutu 512KB ve katı değil ise artan kısım vardır. Bolum Sayisini bir arttır
  if (FileSizeInBytes mod OkumaBuyuklugu) <> 0 then Inc(BolumSayisi);

  MyStream := TMemoryStream.Create;
  try
    for i:=1 to BolumSayisi do
    begin
      readFileChunk(DosyaAdi,MyStream,i,OkumaBuyuklugu);
      // Eger MemoryStream değil string değişken kullanman gerekiyor ise MemoryStream içeriğini aşağıdaki satır ile String değişken içine alabilirsin.
      SetString(StreamInString, PChar(MyStream.Memory), MyStream.Size div SizeOf(Char));
      MyStream.Position := 0; // Bu kodu mutlaka kullanmak gerekli

      // Burada COM portuna MyStream veya StreamInString değişkenlerinden bilgisini gönderebilirsin.
    end;
  finally
    MyStream.Free();
  end;
end;
seci20

Re: bu döngüde sorun nerede ?

Mesaj gönderen seci20 »

ertank yazdı:Aşağıdaki linkte hazır bir kod var. Bu kod ile örneğin bir dosyanın 5nci 512kb kısmını okuman mümkün. Dosyada kaç 512kb bölüm olduğunu dosya boyutunu 512'ye bölerek bulabilirsin. Döngünü buna göre kurabilirsin.

Ancak, sen TMyByteArray tipinde bir veriyi seri port'a gönderiyorsun. Benim aşağıda verdiğim örnek link ise TMemoryStrem kullanıyor. Senin de TMemoryStream kullanman mümkün olursa bu kodu kullanabilirsin.

Zira senin kodunu ben net bir şekilde anlayamadım.

http://stackoverflow.com/questions/2707 ... nto-stream

bahsi geçen kod:

Kod: Tümünü seç

procedure readFileChunk(FileName: string; var MS: TMemoryStream; ChunkNo: Integer; ChunkSize: Int64);
var fs: TFileStream;
begin
  fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  if ChunkSize * (ChunkNo-1) <= fs.Size then
  begin
    fs.Position := ChunkSize * (ChunkNo-1);
    if fs.Position + ChunkSize <= fs.Size then
      ms.CopyFrom(fs, ChunkSize)
    else
      ms.CopyFrom(fs, fs.Size - fs.Position);
  end
  else
    MessageBox(Form2.WindowHandle, 'File does not have so many chunks', 'WARNING!', MB_OK);
  fs.Free;
end;
kullanım şekli:

Kod: Tümünü seç

readFileChunk(FileName,MemoryStream,ChunkNumber,ChunkSize);
Olası dosyayı parça parça okuyan kod örneği. (Test edilmemiştir):

Kod: Tümünü seç

const
  OkumaBuyuklugu = 512 * 1024;
var
  DosyaAdi: string;
  FileSizeInBytes, BolumSayisi: Integer;
  MyStream: TMemoryStream;
  StreamInString: string;
begin
  DosyaAdi := 'c:\okunacak\dosya.bin';
  FileSizeInBytes := FileSize(DosyaAdi);
  BolumSayisi := FileSizeInBytes div OkumaBuyuklugu;
  // Eger dosya boyutu 512KB ve katı değil ise artan kısım vardır. Bolum Sayisini bir arttır
  if (FileSizeInBytes mod OkumaBuyuklugu) <> 0 then Inc(BolumSayisi);

  MyStream := TMemoryStream.Create;
  try
    for i:=1 to BolumSayisi do
    begin
      readFileChunk(DosyaAdi,MyStream,i,OkumaBuyuklugu);
      // Eger MemoryStream değil string değişken kullanman gerekiyor ise MemoryStream içeriğini aşağıdaki satır ile String değişken içine alabilirsin.
      SetString(StreamInString, PChar(MyStream.Memory), MyStream.Size div SizeOf(Char));
      MyStream.Position := 0; // Bu kodu mutlaka kullanmak gerekli

      // Burada COM portuna MyStream veya StreamInString değişkenlerinden bilgisini gönderebilirsin.
    end;
  finally
    MyStream.Free();
  end;
end;
hocam çok teşekkür ederim döngü çok harika çalışıyor ama bir sorun oda şu comport veri yazarken şu şekilde yazıyorum..

Kod: Tümünü seç

const
  OkumaBuyuklugu = 512 * 1024;
var
  DosyaAdi: tfilestream;
  FileSizeInBytes, BolumSayisi: Integer;
  MyStream: TMemoryStream;
  StreamInString: string;
begin
comport1.ShowSetupDialog;
comport1.Open;
  DosyaAdi:=TFileStream.Create('tz',fmOpenRead + fmShareDenyNone);
  DosyaAdi.Seek(0,soFromBeginning);
  FileSizeInBytes := DosyaAdi.Size;
  BolumSayisi := FileSizeInBytes div OkumaBuyuklugu;
  // Eger dosya boyutu 512KB ve katı değil ise artan kısım vardır. Bolum Sayisini bir arttır
  if (FileSizeInBytes mod OkumaBuyuklugu) <> 0 then Inc(BolumSayisi);

  MyStream := TMemoryStream.Create;
  try
    for i:=0 to BolumSayisi do
    begin
      readFileChunk('tz',MyStream,i,OkumaBuyuklugu);
      // Eger MemoryStream değil string değişken kullanman gerekiyor ise MemoryStream içeriğini aşağıdaki satır ile String değişken içine alabilirsin.
      SetString(StreamInString, PChar(MyStream.Memory), MyStream.Size div SizeOf(Char));
      MyStream.Position := 0; // Bu kodu mutlaka kullanmak gerekli
      comport1.WriteStr(StreamInString);
      // Burada COM portuna MyStream veya StreamInString değişkenlerinden bilgisini gönderebilirsin.
    end;
  finally
    MyStream.Free();
  end;
  showmessage('döngü bitti');
end;
ama 1 byte veriyi atlıyor yanı söyle göstereyim size...

bu yazması gerek veri...
Resim

ama bu şekilde yazıyor hep 1 byte veriyi atlıyarak yazıyor...

Resim

bunun sebebi ne olabilir hocam birde i integer dongusunu 0 yaptım yukarda 1 di orjınalınde gene aynı gonderıyor bir farkı olmadı...
ertank
Kıdemli Üye
Mesajlar: 1716
Kayıt: 12 Eyl 2015 12:45

Re: bu döngüde sorun nerede ?

Mesaj gönderen ertank »

Döngünün 1 ile başlaması gerekiyor. Bunu değiştirme.

Daha önce sormamıştım ama hangi Delphi versiyonunu kullanıyorsun?

Aklıma gelen ilk kontrol noktası IntToStr(SizeOf(Char)) değeri nedir?
İkinci olarak MyStrem.Size ile Length(StreamInString) değerleri aynı mı?

Yukarıdaki bilgileri öğrendikten sonra yüksek ihtimalle SetString() fonksiyonu parametreleri değiştirilmesi gerekecek.
seci20

Re: bu döngüde sorun nerede ?

Mesaj gönderen seci20 »

ertank yazdı:Döngünün 1 ile başlaması gerekiyor. Bunu değiştirme.

Daha önce sormamıştım ama hangi Delphi versiyonunu kullanıyorsun?

Aklıma gelen ilk kontrol noktası IntToStr(SizeOf(Char)) değeri nedir?
İkinci olarak MyStrem.Size ile Length(StreamInString) değerleri aynı mı?

Yukarıdaki bilgileri öğrendikten sonra yüksek ihtimalle SetString() fonksiyonu parametreleri değiştirilmesi gerekecek.
hocam 1 olarak döngüyü düzelttim.Delphi xe10 kullanıyorum.Sizin gözünüzden kaçmış sanırsam dosyaadı değişkenini string olarak değiştirmişsiniz ama file size sadece file olanları kabul ediyor string değerlerini kabul etmiyor.Belki ben yanlış biliyorum ama streamdaki size ile file size aynı değerleri veriyor olması gerekli genede yanlış biliyor olabilirim.Son sorunuzda şu şekilde boyutları hocam.

StreamInString:262144
MyStream.Size:524288
yanı aynı değil hocam.Ufak bir notta ben 512kblık bir dosyada denedim.ama recoverydede denesem (örnek verdiğim bir önceki dosya) aynı sekılde 1 byte atlıyor hep...
ertank
Kıdemli Üye
Mesajlar: 1716
Kayıt: 12 Eyl 2015 12:45

Re: bu döngüde sorun nerede ?

Mesaj gönderen ertank »

Kodu ezberden yazmıştım. Test etmeden gönderdim. FileSize ile ilgili sorun bundan sebeptir. Aşağıdaki kodu kullanabilirsin. Böylece FileHandle ile uğraşman gerekmez.

Kaynak: http://stackoverflow.com/questions/1642 ... 0-or-later

Kod: Tümünü seç

function FileSize(const aFilename: String): Int64;
  var
    info: TWin32FileAttributeData;
  begin
    result := -1;

    if NOT GetFileAttributesEx(PWideChar(aFileName), GetFileExInfoStandard, @info) then
      EXIT;

    result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
  end;
SetString satırını aşağıdaki şekilde değiştirerek deneyebilir misin?

Kod: Tümünü seç

SetString(StreamInString, PAnsiChar(MyStream.Memory), MyStream.Size);
seci20

Re: bu döngüde sorun nerede ?

Mesaj gönderen seci20 »

ertank yazdı:Kodu ezberden yazmıştım. Test etmeden gönderdim. FileSize ile ilgili sorun bundan sebeptir. Aşağıdaki kodu kullanabilirsin. Böylece FileHandle ile uğraşman gerekmez.

Kaynak: http://stackoverflow.com/questions/1642 ... 0-or-later

Kod: Tümünü seç

function FileSize(const aFilename: String): Int64;
  var
    info: TWin32FileAttributeData;
  begin
    result := -1;

    if NOT GetFileAttributesEx(PWideChar(aFileName), GetFileExInfoStandard, @info) then
      EXIT;

    result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
  end;
SetString satırını aşağıdaki şekilde değiştirerek deneyebilir misin?

Kod: Tümünü seç

SetString(StreamInString, PAnsiChar(MyStream.Memory), MyStream.Size);
hocam çözdüm tam ben yazıyordum siz cevap vermişsiniz çok teşekkür ederim ALLAH razı olsun şuan tam oldu hocam :) çok tesekkur ederım tekrardan :)
Cevapla