ZX Spectrum > PROGRAMOWANIE

Jak wykryć koniec pliku

(1/2) > >>

CzarusGG:
Witam wszystkich!

ZX Spectrum 48K + Interface 1 + microdrives (2 kasetki) ZX BASIC

Mam problem z końcem pliku. Mam na kasetce microdrive plik tekstowy nieznanej długości. W języku BASIC otwieram strumień kanału "m" wskazujący na ten plik. Próbowałem z niego czytać za pomocą INPUT (każdorazowe wykonanie czyta jedną linię tekstu) oraz INKEY$ (każdorazowe wykonanie czyta tylko jeden znak). Czytam oczywiście w pętli. Ale nie jestem w stanie wykryć końca pliku i program zatrzymuje się z komunikatem End of file.

Czy ktoś wie, jak przeczytać zawartość pliku z microdrive do zmiennej tekstowej?

CzarusGG:
OK. Zostawiam odpowiedź dla potomności, może komuś posłuży.

Odpowiedź brzmi nie da się!  :)

Aby dało się to zrobić musi być spełniony jeden z trzech warunków:

1. Znamy długość pliku i odczytujemy za pomocą INKEY$ tyle bajtów, ile jest w pliku.
2. Jako ostatni bajt mamy zapisany znacznik końca pliku i odczytujemy, do póki nie natrafimy na bajt o wartości tego znacznika. Dla plików tekstowych może to być np. CHR$ 255
3. Jako pierwsza zapisana informacja, to liczba stanowiąca ilość bajtów w pliku. Wtedy za pomocą INPUT odczytujemy długość i mamy spełniony warunek 1. Z tym, że taki plik, przestaje być plikiem tekstowym.

Zatem w moim przypadku, należało doprowadzić do sytuacji z punktu 2.

Skoro miałem już otworzony kanał do czytania (przykładowo 5) z pliku, to:
Otworzyłem kolejny kanał do zapisu w pliku tymczasowym:

OPEN# 6;"m";1;"temp"

Skopiowałem zawartość interesującego mnie pliku.

MOVE #5 TO #6

Dopisałem znacznik końca pliku.

PRINT #6;CHR$ 255;

Zamknąłem oba kanały.

CLOSE# 5: CLOSE# 6

Otworzyłem plik tymczasowy do czytania.

OPEN# 5;"m";1;"temp"

Teraz mogłem odczytać zawartość pliku czytając do póki nie napotkałem bajtu 255. Po przeczytaniu, zamykałem kanał 5 i usuwalem plik tymczasowy.

Poniżej cały podprogram odczytu pliku tekstowego do zmiennej. Podprogram zakłada, że w zmiennej f$ znajduje się nazwa pliku a w zmiennej DRV numer napędu. Zawartość pliku zwracana jest w zmiennej a$

1000 REM ReadFile (f$)
1010 OPEN# 5;"m";DRV;f$
1020 OPEN# 6;"m";DRV;"temp"
1030 MOVE #5 TO #6
1040 PRINT #6;CHR$ 255;
1050 CLOSE# 5
1060 CLOSE# 6
1070 OPEN# 5;"m";DRV;"temp"
1080 LET a$ = ""
1090 LET k$ = INKEY$#5
1100 IF k$ = CHR$ 255 THEN GOTO 1130
1110 LET a$ = a$ + k$
1120 GO TO 1090
1130 CLOSE# 5
1140 REMOVE "m";DRV;"temp"
1150 RETURN

tooloud:

--- Cytat: CzarusGG w 2024.03.05, 10:02:07 ---
Odpowiedź brzmi nie da się!  :)

--- Koniec cytatu ---

yyyyy że jak?


--- Cytat: CzarusGG w 2024.03.05, 10:02:07 ---1. Znamy długość pliku i odczytujemy za pomocą INKEY$ tyle bajtów, ile jest w pliku.

--- Koniec cytatu ---

1. a co zawiera header pliku jak nie te informacje? Może kluczowe jest, że w BASICu nie wszystko można z komend BASICa, bo jak sama nazwa wskazuje jest to bardzo podstawowe czyli... BASIC :)

2. Metoda z odczytem sekwencyjnym "dopóki to nie EOF" jest prosta jak cep, z tym, że ma jedną wadę - może Ci zabraknąć pamięci, chyba, że to od razu buforujesz czy zapisujesz na inny otwarty do zapisu stream... Ja robiłem coś takiego mając podłączony emutor MD i normalne MD.

matofesi:
@tooloud ad. 1 Mam wrażenie, że nagłówek plików sekwencyjnych nie zawiera długości...
ad. 2 Tu dla odmiany jak rozumiem problem polega na tym, że nie ma "dopóki EOF" tylko jak jesteś za "EOF" to BASIC wywala błąd.

tooloud:
a to nie jest tak, że dostęp do pliku jest sekwencyjny czyli czytamy go "bajtowo"? Nie ma czegoś takiego jak bajt po EOF, bo EOF przecież zamyka długość pliku. Czyli to jest null.
Header zależy od systemu plików czyli "DOS"a. MD/IF1 ma headery tylko są bardziej sektorowe. Czyli - da się to odczytać, ale nie z BASIC'a. Jak długi by nie był nasz program, to minimalnie i tak zajmie 512 bajtów danych zapisu + informacje sektorowe.

; Offset Length Name Contents
; ------------------------------
; 0 1 HDFLAG Value 1, to indicate header block
; 1 1 HDNUMB sector number (values 254 down to 1)
; 2 2 not used (and of undetermined value)
; 4 10 HDNAME microdrive cartridge name (blank padded)
; 14 1 HDCHK header checksum (of first 14 bytes)
;
; 15 1 RECFLG - bit 0: always 0 to indicate record block
; - bit 1: set for the EOF block
; - bit 2: reset for a PRINT file
; - bits 3-7: not used (value 0)
;
; 16 1 RECNUM data block sequence number (value starts at 0)
; 17 2 RECLEN data block length (<=512, LSB first)
; 19 10 RECNAM filename (blank padded)
; 29 1 DESCHK record descriptor checksum (of previous 14 bytes)
; 30 512 data block
; 542 1 DCHK data block checksum (of all 512 bytes of data
; block, even when not all bytes are used)
;
; 543 bytes altogether. Beware: .mdr files have an additional byte at the end.
; If it's !=0 this indicates "write protection".

Nawigacja

[0] Indeks wiadomości

[#] Następna strona

Idź do wersji pełnej