Jak přečist poslední řadek z text souboru. – Delphi – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Jak přečist poslední řadek z text souboru. – Delphi – Fórum – Programujte.comJak přečist poslední řadek z text souboru. – Delphi – Fórum – Programujte.com

 

Borisek0
Stálý člen
31. 12. 2024   #1
-
0
-

 Dobrý den.

Je jine řešení?
Da se přimo nastavit ten poslední řadek misto toho
while not Eof(myFile) do
Děkuji.
 

begin
 AssignFile(myFile, 'Test.txt');
   Reset(myFile);
  while not Eof(myFile) do
   begin
    ReadLn(myFile, m);
   end;
   ShowMessage(m);
   CloseFile(myFile);
end;                           
Nahlásit jako SPAM
IP: 95.173.82.–
gna
~ Anonymní uživatel
1898 příspěvků
31. 12. 2024   #2
-
0
-

Funkcí Seek jde nastavit pozici, ze které se bude číst, tak můžeš od konce souboru hledat konec řádku (byte s hodnotou 10).

Nahlásit jako SPAM
IP: 213.211.51.–
JerryM0
Věrný člen
31. 12. 2024   #3
-
0
-

#2 gna
https://docwiki.embarcadero.com/Libraries/Sydney/en/System.SysUtils.FileSeek

https://stackoverflow.com/questions/17602044/read-binary-file-in-delphi

https://docwiki.embarcadero.com/CodeExamples/Athens/en/TBinaryReader_and_TBinaryWriter_(Delphi)

ty děláš v Delphi 12.x ? tý jo ... woooooooooooou

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:9dae:6f76:9fab:8450...–
Borisek0
Stálý člen
1. 1. 2025   #4
-
0
-

Děkuji.
Moc v tom nedělam.
Když jsem kouknul na ten stackoverflow.com, není pak lepši ten soubor načist do StringList nebo TMemoryStream?
Ten soubor je na raspberry v /dev/shm/. Což je ramdisk.
Takže data budou po řadcich přibyvat dokud se raspi ktere jede 24/7 nerestartuje.

Nahlásit jako SPAM
IP: 95.173.82.–
JerryM0
Věrný člen
1. 1. 2025   #5
-
0
-

to záleží na tom, jak je ten soubor velkej a jestli se rozrůstá nebo ne. ano, můžeš ho načíst celej najednou do paměti a pak nastavit ukazatel na konec. u textových souborů, je na konci každého řádku CR+LF. čili 2 ASCII znaky 0x0D + 0x0A - to musíš zjistit co tam je. Záleží na tom jak k souboru přistupuješ jestli v binárním modu nebo textovém. v binárním modu visíš jednotlivé znaky a v textovém vidíš řádky. Takže když to budeš načítat v textovém tak načteš všechny řádky do pole stringů a pak je procházíš, vhodná colekce je např.

https://docwiki.embarcadero.com/Libraries/Athens/en/System.Generics.Collections.TList

u binárního přístupu načteš všechny data do pole např.

https://stackoverflow.com/questions/5801542/how-can-i-assign-a-value-to-a-char-array

a pak nastavíš ukazatel na konec a pak procházíš data od posledního prvku směrek k prvnímu a hledáš skvenci 0D0A což je konec řádky (občas je tu jen 0D).

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:4d38:9104:ff88:6840...–
Borisek0
Stálý člen
1. 1. 2025   #6
-
0
-
Nahlásit jako SPAM
IP: 95.173.82.–
JerryM0
Věrný člen
1. 1. 2025   #7
-
0
-

poslední řádek je 18. řádek a je tam jen jeden znak. Asi 0x0D. To takhle nejde poznat.

jestli je ten soubor takhle krátkej vždycky a nezvětšuje se tak bych ho asi načet celej do paměti do kolekce TList

https://docwiki.embarcadero.com/CodeExamples/Sydney/en/Generics_Collections_TList_(Delphi)

je to nejjednodušší. A otevřel bych ho jako textovej soubor a četl po řádcích - příkaz Readln. Při načítání můžeš vynechat řádky, kde je počet znaků menší než třeba 28 protože 29. znak by měl být asi 0x0D.

Jinak doporučuju zobrazit si ten soubor např. v Listeru ve windows v hexa formátu:

Připojen obrázek.

abys viděl co je tam za znak/znaky na konci

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:4d38:9104:ff88:6840...–
Borisek0
Stálý člen
1. 1. 2025   #8
-
0
-

#7 JerryM
Do souboru se ukladaji data po řadcich a přibyvaji.
Ted jsem to smazal. Než se raspbery restartuje, muže být řadku i několik tisic.
Do souboru uklada data Node-Red.
https://ibb.co/yVm4Sg8

Nahlásit jako SPAM
IP: 95.173.82.–
gna
~ Anonymní uživatel
1898 příspěvků
1. 1. 2025   #9
-
0
-

Pokud potřebuješ jen poslední řádek, tak asi nemá smysl načítat celý soubor do paměti. A pokud ten soubor není obrovský, že by postupné čtení trvalo dlouho, tak u toho zůstaň když ti to funguje. Když nemáš reálnou potřebu to optimalizovat, tak to udělej jakkoliv se ti to líbí.

Ale pokud se opravdu potřebuješ vyhnout nadbytečnému čtení, tak použuj ten seek. Můžeš načíst jeden blok, do kterého by se ten řádek měl vejít, nebo v cyklu číst dokud nedostaneš celý řádek, jak chceš.

Tohle mi funguje ve FPC na rextester.com. Jako buffer jsem použil AnsiString jen pro jednoduchost (a protože si Pascal moc nepamatuju), nemusí ti to vyhovovat. 

uses
    sysutils, strutils, math;

var
    f: file;
    str: ansistring;

begin
    // otevrit tenhle zdrojak
    assign(f, extractfilepath(paramstr(0)) + {$I %FILE%});
    filemode := 0;
    reset(f, 1);

    // nacist poslednich 200 bytu
    setlength(str, min(200, filesize(f)));
    seek(f, filesize(f) - length(str));
    blockread(f, str[1], length(str));

    close(f);

    str := trimright(str);
    str := copy(str, rpos(#10, str) + 1, length(str));
    writeln('last line: ', str);
end.
Nahlásit jako SPAM
IP: 213.211.51.–
JerryM0
Věrný člen
1. 1. 2025   #10
-
0
-

Aha tak ty tam máš jen jeden ukončovací ASCII znak řádku a to je 0x0A - LineFeed. Když se soubor zvětšuje a je evidentní, že řádek má vždy JEN 29 znaků a na konci každého řádku je 0x0A. Takže v tomto případě bych asi zvolil binární přístup k souboru. Příklad je tady:

https://stackoverflow.com/questions/17602044/read-binary-file-in-delphi

A místo AnsiChar:
Buffer: array[0..1023] of AnsiChar;
dáš jen Char. Což je 8 bitů na znak. Klasická ASCII sada.

Takže:

1/ otevřeš soubor v binárním modu,

2/ nastavíš příkazem seek pozici v souboru na pozici: (počet znaků souboru - 43) 

https://stackoverflow.com/questions/1642220/getting-size-of-a-file-in-delphi-2010-or-later

https://docwiki.embarcadero.com/Libraries/Sydney/en/System.Classes.TStream.Size

3/ přečteš znaky od nastavené pozice až do konce souboru do pole znaků Char

4/ začneš pole procházet dokud nenarazíš na znak 0x0A, což je konec předposlední řádky v souboru

5/ a zbytek znaků v poli je poslední řádek souboru se znakem 0x0A na konci. Je nutné upozornit, že na konci asi muže být "ASI" víc 0x0A znaků.

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:4d38:9104:ff88:6840...–
Borisek0
Stálý člen
1. 1. 2025   #11
-
0
-

Nema vždy 29 znaku.
17.8|59|42|8:3:58 - 1/1/2025
čas i datum se bude určitě měnit a to třeti je baterka, tak když strčim novou, tak misto 42 bude 100.
 

Nahlásit jako SPAM
IP: 95.173.82.–
JerryM0
Věrný člen
1. 1. 2025   #12
-
0
-

co kdyby si nám dal odkaz na ten datový soubor ? abysme si ho mohli stádhnout

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:4d38:9104:ff88:6840...–
JerryM0
Věrný člen
1. 1. 2025   #13
-
0
-

aha nemá vždy 29 znaků, :) tak to asi navrhoval nějakej mamlas protože tim sis to výrazně zesložitil :) :) :) :) :)

a jestli to chápu správně tak tam místo "přibližně" 25-29 znaků může bejt i jenom jeden znak a to 0x0A. to je paráda ... je vidět že jsi správný datový inženýr :) :) :) :)  a své práci rozumíš.

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:4d38:9104:ff88:6840...–
JerryM0
Věrný člen
1. 1. 2025   #14
-
0
-

pokud je počet znaků na řádce variabilní, tak je dobré dát řádku do oddělovačů aby se to zjednodušilo např:

{17.1.2024;250;13;200}0x0A

{17.1.2024;1;13;10}0x0A

{17.1.2024;0;13;1000}0x0A

{}0x0A

poslední řádek značí prázdný záznam ... chápeš jo ?

takže jde o to, jestli můžeš formát toho datového souboru změnit :)

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:4d38:9104:ff88:6840...–
Borisek0
Stálý člen
1. 1. 2025   #15
-
0
-

Tak ten mamlas jsem byl ja.
V nodu je uzel mqtt in. přes který si odchytim data teplota, vlhkost a stav baterk.

Pak je uzel function kde fi mužu udělat co potřebuji v javascript.
 

var d = new Date();
var payload = msg.payload;
var day = d.getDate();
var month = d.getMonth() + 1; 
var year = d.getFullYear();
d.getHours();
d.getMinutes();
d.getSeconds();
var currentDate = `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()} - ${day}/${month}/${year}`;
msg.payload = payload.temperature + "|" + payload.humidity + "|" + payload.battery + "|" + currentDate;
return msg;

A pak ten vysledek msg odešli přes uzel write file
 

Nahlásit jako SPAM
IP: 95.173.82.–
JerryM0
Věrný člen
1. 1. 2025   #16
-
0
-

ano tak asi bych tam přidal ty závorky nebo cokoliv jiného, co by to zjednodušilo. ideální by byla samozřejmě konstantní délka řádku. takže před příkazem
return msg;
bys to nějak doplnl mezerama na konstatní délku.

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:4d38:9104:ff88:6840...–
gna
~ Anonymní uživatel
1898 příspěvků
1. 1. 2025   #17
-
0
-

Jerry, kolik jsi toho o půlnoci vypil? Na co nějaký závorky :)

Nahlásit jako SPAM
IP: 213.211.51.–
JerryM0
Věrný člen
1. 1. 2025   #18
-
0
-

já vim... dělá to on ... je to JEHO práce ... proč si to dělat jednoduchý když to de dělat složitě že :) :) :)

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:4d38:9104:ff88:6840...–
Borisek0
Stálý člen
1. 1. 2025   #19
-
0
-

Nechapu tu konstantní delku když se čas i datum mění.
Mužu vždy na konec řadku přidat nějaký znak.Třeba

18.3|58|42|9:41:53 - 1/1/2025>
 

Nahlásit jako SPAM
IP: 95.173.82.–
gna
~ Anonymní uživatel
1898 příspěvků
1. 1. 2025   #20
-
0
-

#18 JerryM
Mezi řádky je přirozený oddělovač - odřádkování. Takže tam nemusí přidávat nějaký vlastní závorky.

Nahlásit jako SPAM
IP: 213.211.51.–
gna
~ Anonymní uživatel
1898 příspěvků
1. 1. 2025   #21
-
0
-

#19 Borisek
18.03|058|042|09:41:53 - 01/01/2025

Nahlásit jako SPAM
IP: 213.211.51.–
JerryM0
Věrný člen
1. 1. 2025   #22
-
0
-

tak fajn nepřidávej ho tam ...

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:4d38:9104:ff88:6840...–
JerryM0
Věrný člen
1. 1. 2025   #23
-
0
-

znak ">" nepoužívej, je to matoucí, ideální by bylo, kdyby každá položka na tom řádku měla konstantní délku a tím pádem by měl konstantní délku i celý řádek. a místo ">" se používá mezera ASCII32. samozřejmě můžeš použíi i prasování řádku, ale tim si to děláš složitější 

Nahlásit jako SPAM
IP: 2a00:1028:83bc:e52a:4d38:9104:ff88:6840...–
MilanL+1
Grafoman
2. 1. 2025   #24
-
0
-

#15 Borisek
No pokud tam máš na to logování vlastní script máš 2 možnosti:

1) pevnou délku řádky - tzn formátováním doplnit 0 nebo mezery, abys měl stejně dlouhé řádky. Pak bude při čtení poslední stačit zjistit délku souboru z ní pak výpočtem počet řádků a následně si pomocí seeku nastavit místo začátku čtení.

2) vytvořit si soubor pro poslední záznam, kde se bude jen 1 řádka, která se bude neustále přepisovat.

Dále bych viděl ještě další možnosti, ale to už by vyžadovalo sofistikovanější přístup.

Nahlásit jako SPAM
IP: 91.139.9.–
Borisek0
Stálý člen
7. 1. 2025   #25
-
0
-

Tak možnost 2 mně nenapadla.
Nejjednodužší a nejrychlejši.
Dik.
 

Nahlásit jako SPAM
IP: 95.173.82.–
gna
~ Anonymní uživatel
1898 příspěvků
7. 1. 2025   #26
-
0
-

No jo, on je ten seek tak strašně složitej.

Nahlásit jako SPAM
IP: 213.211.51.–
remmidemmi0
Věrný člen
14. 1. 2025   #27
-
0
-

Je ten problém ještě aktuální, nebo ne?

Za prvé, v úvodu dotazu mi chybí info, na jakém systému a v jakém jazyce se má problém řešit.... Klasika, každý mlaadý programátor si myslí, že existuje jen ten systém a programovací jazyk, který on používá a všichni to musí chápat. :)

Za druhé, řešení na HP9825A (16-bitový počítsač z roku 1976 zde https://www.hpmuseum.org/hp9825.htm) - používám já :) , toto řešení je snadné a používá se například pro čtení věty zaznamenané v souboru na páskové kazetě.

Má-li se přečíst poslední věta, souboru, postup je následující:

1/ dotaz na délku souboru (jeden příkaz). Hodnota se vrátí do proměnné.

2/ nastavení ukazatele na konec souboru dle získané hodnoty v proměnné

3/ zjištění zda před EOF je EOL.

4/ jestli před EOF je znak EOL, vyhledá se předchozí EOL. Tím se zjistí délka poslední věty a ukazatel je nastaven na předposlední EOL.  Přečtou se všechny znaky od ukazatele+1 do EOL a uloží do stringu.

5/ jestli před EOF není EOL,vyhledá se první EOL odzadu. Tím se zjistí délka poslední věty a ukazatel je nastaven na předposlední EOL.  Přečtou se všechny znaky od ukazatele+1 do EOF a uloží do stringu

V případě HP9825A je rychlost dána rychlostí čtení dat z páskové kazety. Stejně, ale rychleji to funguje při čtení ze souboru na disketové mechanice (8" floppy  HP9885M - viz zde: https://www.ebay.co.uk/itm/135222294124?msockid=32c5b37b45d069042d55a60f44b7684c)

Prográmek pro přečtení poslední věty v souboru je velmi krátký, u mne v jazyce HPL pouze 8 řádek.

Nahlásit jako SPAM
IP: 194.212.254.–
Borisek0
Stálý člen
14. 1. 2025   #28
-
0
-

#27 remmidemmi Ja myslel, že když jsme v sekci DELPHI, tak není třeba uvadět v jakem jazyce to řešim.
Všici to tu pochopili.
  

Nahlásit jako SPAM
IP: 95.173.82.–
Zjistit počet nových příspěvků

Přidej příspěvek

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 10 hostů

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032025 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý