Problem z plikiem do odczytu (błąd 105)

0

Witam.
Mam problem z programem, który korzysta z odczytu i zapisu danych do pliku.

Część głównego pliku kontakty.pas:

uses CRT;

type Kontakt=record
     imie, nazwisko, telefon, email, grupa:Array[1..100] of String;
end;

var menu:Char;
    plik:Text;
    osoba:Kontakt;
    i,nr_grupy:Byte;
    link:String;

procedure OdczytGrup;
  begin
    i:=0;
    While EOF(plik) Do
      begin
        i:=i+1;
        Writeln(plik, osoba.grupa[i]);
      end;
  end;

procedure DodajGrupe;
  begin
    Write('Podaj nazwe nowej grupy kontaktow: ');
    {Otworzenie pliku grupy.dat i wyliczenie ilosci istniejacych grup}
    Assign(plik, './dane/grupy.dat');  //tutaj wyskakuje błąd 105, który mówi, że nie można otworzyć pliku do odczytu
    Reset(plik);
    FileMode:=0;
    nr_grupy:=0;
    OdczytGrup;
    Close(plik);
    {Nadanie numeru dla nowej grupy i stworzenie jej jako oddzielnego pliku tekstowego}
    nr_grupy:=i+1;
    Readln(osoba.grupa[nr_grupy]);
    link:='./dane/' + osoba.grupa[nr_grupy] + '.dat';
    Assign(plik, link);
    ReWrite(plik);
    Close(plik);
{otworzenie jeszcze raz pliku grupy.dat oraz dopisanie do listy nowej grupy}
    Assign(plik, './dane/grupy.dat');
    Append(plik);
    Readln(plik, osoba.grupa[nr_grupy]);
    Close(plik);
  end;

Katalog dane, w którym znajduje się plik grupy.dat, jest w tym samym katalogu co kontakty.pas.
Pulpit/kontakty/dane/grupy.dat
Pulpit/kontakty/kontakty.pas

Jaka może być przyczyna tego problemu? Czy to ma znaczenie dla kompilatora czy owy plik został stworzony ręcznie czy przez procedurę ReWrite?

1
Vendetta napisał(a):

Jaka może być przyczyna tego problemu? Czy to ma znaczenie dla kompilatora czy owy plik został stworzony ręcznie czy przez procedurę ReWrite?

Przyczyny są dwie: brak TBrain i brak TGoogle.

Aż tak trudno wpisać kod błędu z dopiskiem Pascal do googla? I aż tak trudno potem do tego użyć debuggera? No widać dla Ciebie jest to zbyt trudne.

0

I po co ten spam -321oho? Jak nie chcesz pomóc to lepiej nic nie pisz... Wiem co oznacza błąd 105, bo sprawdziłem. Debuggerem znalazłem miejsce, w którym ten błąd się znajduje. Jedno i drugie napisałem w pierwszym poście. To nie zmienia faktu, że nie umiem sobie poradzić z tym błędem. Sama procedura Reset powinna otworzyć plik w trybie do odczytu. Dodatkowo ustawiłem FileMode na 0 aby ręcznie ustawić plik do odczytu. To również nie pomogło.

Znajdzie się ktoś kto podpowie co może być nie tak?

dodane:
Właśnie zauważyłem, że źle zaznaczyłem miejsce błędu. Powinno być linijkę niżej: Reset(plik);

dodane2:
Próbowałem z plikiem 'grupy.dat' stworzonym ręcznie w katalogu 'dane' oraz stworzonym przez procedurę ReWrite. W obu przypadkach plik nie jest otwarty do odczytu i pojawia się exitcode 105.
Z drugiej strony plik stworzony za pomocą ReWrite jest chyba góry otwierany w trybie do zapisu a nie do odczytu.
A jak to jest jeżeli mój plik jest w tej chwili pusty? Czy można otworzyć do odczytu pusty plik? Jeśli nie to byłoby to rozwiązaniem mojego problemu. W pętli while..do sprawdzam czy wskaźnik jest na końcu pliku. Jeżeli plik jest pusty to czy istnieje wskaźnik? Jeśli tak to jest on zarówno na początku i na końcu pliku.

0

Dodatkowo ustawiłem FileMode na 0 aby ręcznie ustawić plik do odczytu.

Że tu?

Reset(plik);
    FileMode:=0;

Najpierw otwieram, potem stwierdzam że jednak tylko do odczytu!

Kontakt=record
     imie, nazwisko, telefon, email, grupa:Array[1..100] of String;
end;

Genialny rekord.

I po co ten spam -321oho? Jak nie chcesz pomóc to lepiej nic nie pisz... Wiem co oznacza błąd 105, bo sprawdziłem. Debuggerem znalazłem miejsce, w którym ten błąd się znajduje. Jedno i drugie napisałem w pierwszym poście. To nie zmienia faktu, że nie umiem sobie poradzić z tym błędem

No bo ty zakładasz, że ja 10 razy przewertuje twój kod w poszukiwaniu linii które pokazują że użyłem wspomnianych narzędzi. Serio, nie marnuję czasu na patrzenie w słaby kod o ile nie ma takiej potrzeby, skoro coś szukałeś, to zaznacz to nie tylko w komentarzach, ale też w tekście.
Tak przy okazji, nie wiesz co to spam. I jeżeli uważasz że nie chcę ci pomóc, to wcale nie mam zamiaru ci pomagać na siłę. Uważaj na słowa, bo możesz nieporozumienie zamienić w brak chęci pomocy.

0

Ja nic nie zakładam, poprosiłem tylko o podpowiedź. Wszystko co trzeba napisałem i ustawiłem komentarze. Nie przeczytać, zwymyślałeś na mnie, a na końcu napisałeś, że to moja wina, że nie przeczytałeś ;) Ale mniejsza z tym...

Właśnie widzę, że trochę namieszałem w kodzie.
Faktycznie FileMode powinno być przed Reset.

Dodatkowo źle stworzyłem własny typ. Poprawiłem na taki:

type Kontakt=record
     imie, nazwisko, telefon, email, grupa:String;
end;

var osoba:Array[1..100] of Kontakt;

Następnie wyskoczyło kilka błędów. Zmieniłem osoba.grupa[i] na osoba[i].grupa i jestem w punkcie wyjścia. Exitcode=105.

0
Vendetta napisał(a):

jestem w punkcie wyjścia. Exitcode=105.

No to biorąc pod lupę np. ten kod: Assign(plik, './dane/grupy.dat');

  1. Czemu kropka jest na początku?
  2. Czy pracujesz na linuksie, że odwracasz slasze?

Jeżeli wciąż będziesz mieć problem, wygeneruj jakiś mały example dla nas.

0

Ten kod akurat pisałem pod Windowsem używając FPC.
Kropka oznacza aktualny katalog, slashe są w porządku. Gdyby ścieżka do pliku była nieprawidłowa to wyrzuciłoby exitcode=3 a gdyby kompilator nie znalazł pliku w katalogu to wyrzuciłby exitcode=2.

Poza tym taki kod tworzy mi plik w odpowiednim katalogu, a więc działa prawidłowo w tym samym programie:

          Assign(plik, './dane/grupy.dat');
          Rewrite(plik);
          Close(plik);
0

Kropka oznacza aktualny katalog, slashe są w porządku.

Wiem, że kropka oznacza aktywny katalog, tylko nie rozumiem po co ją stosujesz. I slashe są w złą stronę.

Gdyby ścieżka do pliku była nieprawidłowa to wyrzuciłoby exitcode=3 a gdyby kompilator nie znalazł pliku w katalogu to wyrzuciłby exitcode=2.

Pytanie brzmi, kto wie więcej o programowaniu w FPC.

Poza tym taki kod tworzy mi plik w odpowiednim katalogu, a więc działa prawidłowo w tym samym programie:

Zapis<>Odczyt. Raz jeszcze mówię, że chyba póki co więcej wiem o programowaniu w FPC i dlatego to ja pomagam tobie, a nie ty mi.
Więc sprawdź z odwróconymi slashami, względnie bez wybierania aktualnego katalogu, ale przez np. pełen path.

Jeżeli powyższe kroki nie pomogą to:

-321oho napisał(a)

wygeneruj jakiś mały example dla nas.

0

Nie ważne czy podam ścieżkę względną czy bezwzględną z backslashami to wywala mi exitcode=3 .Poza tym pierwszy raz spotykam się z takim czymś. Do tej pory używałem slashy i kropki w linkach (w FPC) i działało prawidłowo.

Napisz mi jeszcze o jaki przykład konkretnie chodzi to wygeneruje za chwilkę i wrzucę.

0

Napisz mi jeszcze o jaki przykład konkretnie chodzi to wygeneruje za chwilkę i wrzucę.

O taki, który pozwoli na moim kompilatorze i debuggerze uzyskać takie same wyniki jak u ciebie przy ograniczonej do minimum wielkości.

0
uses CRT;

type Kontakt=record
     imie, nazwisko, telefon, email, grupa:String;
end;

var menu:Char;
    plik:Text;
    osoba:Array[1..100] of Kontakt;
    i,nr_grupy:Byte;
    link:String;

procedure OdczytGrup;
  begin
    i:=0;
    While EOF(plik) Do
      begin
        i:=i+1;
        Writeln(plik, osoba[i].grupa);
      end;
  end;

procedure DodajGrupe;
  begin
    Write('Podaj nazwe nowej grupy kontaktow: ');
    Assign(plik, './dane/grupy.dat');
    FileMode:=2;
    Reset(plik);
    nr_grupy:=0;
    OdczytGrup;
    Close(plik);
    nr_grupy:=i+1;
    Readln(osoba[nr_grupy].grupa);
    link:='./dane/' + osoba[nr_grupy].grupa + '.dat';
    Assign(plik, link);
    ReWrite(plik);
    Close(plik);
    Assign(plik, './dane/grupy.dat');
    Append(plik);
    Readln(plik, osoba[nr_grupy].grupa);
    Close(plik);
  end;

BEGIN
  Repeat
    ClrScr;
    Writeln('Menu:');
    Writeln('6 - Dodaj grupe kontaktow');
    Writeln('9 - Tworzenie pliku grupy.dat');
    Writeln('0 - Zamknij program');
    Writeln();
    i:=0;
    Repeat
      menu:=readkey;
    Until (menu>='0') AND (menu<='9');
    case menu of
      '6': DodajGrupe;
      '9':
        begin
          Assign(plik, './dane/grupy.dat');
          Rewrite(plik);
          Close(plik);
        end;
      '0': exit;
    end;
  Until (menu='0');
  readkey;
END.

0

Pomijając to, że nie dołączyłeś instrukcji obsługi, to po użyciu 9 potem 6 otrzymuję następujące informacje o błędzie:
Stack frame:
#0 SYSTEM_HANDLEERRORADDRFRAME$LONGINT$POINTER$POINTER at :0
#1 SYSTEM_HANDLEERRORFRAME$LONGINT$POINTER at :0
#2 U_SYSTEM_OUTPUT at :0
#3 U_SYSINITPAS_ENTRYINFORMATION at :0
#4 U_SYSTEM_ENTRYINFORMATION at :0
#5 fpc_iocheck at :0
#6 ODCZYTGRUP at p206902.lpr:19
#7 DODAJGRUPE at p206902.lpr:31
#8 main at p206902.lpr:60

Twoje odczytywanie grup kończy się próbą zapisania do pliku pustego stringa, co kończy się błędem 105. Poza tym piękny warunek While EOF(plik) Do. Nie ma to jak twierdzić, że się umie używać debuggera, co nie?

0
Vendetta napisał(a):
procedure OdczytGrup;
  begin
    i:=0;
    While EOF(plik) Do
      begin
        i:=i+1;
        Writeln(plik, osoba[i].grupa);
      end;
  end;

procedure DodajGrupe;
  begin
    Write('Podaj nazwe nowej grupy kontaktow: ');
    Assign(plik, './dane/grupy.dat');
    FileMode:=2;
    Reset(plik);
    nr_grupy:=0;
    OdczytGrup;

Najpierw otwierasz plik do odczytu a później chcesz do niego zapisywać.

Vendetta napisał(a):

//tutaj wyskakuje błąd 105, który mówi, że nie można otworzyć pliku do odczytu

Nie. Ten błąd mówi:
File not open for output

0

Najpierw otwierasz plik do odczytu a później chcesz do niego zapisywać.

Filemode=2 oznacza że pliki będą otwierane w trybie zapis-odczyt.
FileMode

0
-321oho napisał(a):

Najpierw otwierasz plik do odczytu a później chcesz do niego zapisywać.

Filemode=2 oznacza że pliki będą otwierane w trybie zapis-odczyt.
FileMode

Więc dlaczego FPC zgłasza błąd 105?

Wyjaśnieniem jest deklaracja zmiennej plik która jest typu Text, o czym zorientowałem się dopiero teraz.

http://lazarus-ccr.sourceforge.net/docs/rtl/system/filemode.html napisał(a)

Default file mode for untyped files.

No i się wszystko wyjaśniło.

0

Błąd powstaje, ponieważ po otwarciu pliku do odczytu (Reset), próbuje do niego pisać (Writeln).

0
pelsta napisał(a):

Błąd powstaje, ponieważ po otwarciu pliku do odczytu (Reset), próbuje do niego pisać (Writeln).

Natomiast nie powstaje dlatego, jak mogą niektórzy błędnie założyć, że filemode jest źle ustawione, bo nie wyjaśniłeś tej zależności. Po prostu wedle dokumentów FPC filemode nie ma wpływu na czytanie plików tekstowych.

0

No jasne, że tak. Pomyliłem procedury. Po zmianie read na write i write na read wszystko działa jak należy. Dzięki Pelsta!
-321oho Tobie również dzięki za zauważenie brakującego not.
Muszę bardziej uważać, bo straszne błędy robię przez nieuwagę, aż wstyd :P

dodane:
Procedura Reset z automatu ustawia plik do odczytu a Rewrite do zapisu. FileMode użyłem dopiero gdy czepiało się, że nie może otworzyć pliku w trybie do odczytu. To była próba ustawienia na siłę młotkiem co oczywiście nie miało zupełnie sensu :)

0

Procedura Reset z automatu ustawia plik do odczytu a Rewrite do zapisu.

Błąd! Te procedury kierują się ustawieniem filemode jeżeli pracujesz na plikach innych niż tekstowe.
Generalnie to powinno się używać czegoś nowszego niż ten stary mechanizm, ale wiele osób (w tym ja) ma te przyzwyczajenia...

I nie zapomnij oznaczyć rozwiązania ptaszkiem.

0
Vendetta napisał(a)

dodane:
Procedura Reset z automatu ustawia plik do odczytu a Rewrite do zapisu. FileMode użyłem dopiero gdy czepiało się, że nie może otworzyć pliku w trybie do odczytu.

A czy Ty w ogóle kiedyś czytałeś cokolwiek na temat obsługi plików...? W każdym kursie jest napisane o procedurach/funkcjach do odczytu/zapisu danych; W szczególności jeśli chodzi o pliki tekstowe, które jako pierwsze bierze się pod lupę przy nauce pierwszego języka;

Nie wiem (lub nie doczytałem) z jakiego środowiska kożystasz, jednak błąd o kodzie 105 występuje także wtedy, gdy w kodzie modułu nie ma podanej odpowiedniej dyrektywy (np. {$APPTYPE CONSOLE} w D7 przy aplikacji konsolowej), czyli nie wskaże się wyjścia;

Tak więc przyczyn może być wiele, jednak debugger pomoże zawęzić poszukiwania;


-321oho napisał(a)

Błąd! Te procedury kierują się ustawieniem filemode jeżeli pracujesz na plikach innych niż tekstowe.

Więc właśnie - jeśli korzystamy z plików tekstowych to nie ma sensu bawić się FileMode i będzie wszystko poprawnie, a jeśli nie działa - debugger;

@**-**321oho - znowu nowa ksywka? :>

0

@321oho - znowu nowa ksywka? :>

Znowu ludzie przenoszą ten minus w dziwne miejsca.
Tak, nowa ksywka, bo monk się bawił forum i jeszcze jakiś czas temu odpowiedzi postowane jako '-123oho' dziwnym trafem znikały. Bez obaw, mam z 5 nicków w zapasie. I tak po moim stylu wypowiedzi zawsze można mnie rozpoznać :> .

Wściekły programista napisał(a)

Byle nie swoim ptaszkiem;

Mhm...

Nie wiem (lub nie doczytałem) z jakiego środowiska kożystasz, jednak błąd o kodzie 105 występuje także wtedy, gdy w kodzie modułu nie ma podanej odpowiedniej dyrektywy (np. {$APPTYPE CONSOLE} w D7 przy aplikacji konsolowej), czyli nie wskaże się wyjścia;

Tak, tylko nie to tutaj jest raczej problemem. Chociaż w sumie to wszystko jest możliwe po tym gdy pytacz stwierdził że zna debugger tylko po to żeby mnie utrudnić poszukiwania błędu.

0

Nie domawiaj tego co nie było powiedziane -321oho. Napisałem, że użyłem debuggera i znalazłem miejsce błędu. Na pewno perfekcyjnie nie znam, bo się uczę dopiero. A poza tym ten FPC to z innej epoki jest. Tyle co sam posiedziałem przy debuggerze i popatrzyłem co jak się robi to wiem, bo poradnika nigdzie nie znalazłem żadnego.

0

Napisałem, że użyłem debuggera i znalazłem miejsce błędu.

Więc nie wprowadziłeś mnie w błąd?

Na pewno perfekcyjnie nie znam, bo się uczę dopiero.

Dobrze, nie zmienia to faktu że wprowadziłeś mnie w błąd.

A poza tym ten FPC to z innej epoki jest.

Najnowsza wersja wyszła na początku 2012, ale ostatnio gdy spytałem kiedy będzie nowa wersja, dostałem informację o powstaniu branchu 2.6.2. FPC nie jest z innej epoki, FPC to nowoczesny i najlepszy z darmowych kompilatorów Pascala. Jest na tyle dobry że staje w szaranki z Delphi. To, ze tobie się wydaje że jest z innej epoki to środowisko rodem TP, które nie jest już rozwijane i jest przewidziane jako domyślne środowisko na systemy, które nie wspierają okienek i domyślnie mają ograniczone możliwości. To, że ograniczasz możliwości FPC używając go w takim środowisku na platformie, na którą jest Lazarus, to tylko i wyłącznie twoja wina. Zawsze proponuję używanie Lazarusa ( www.lazarus.freepascal.org ), właśnie ze względu na surowe środowisko FPC-IDE, które wychodzi śmiesznie przy Lazarusie. No ale przecież nic na siłę. Możesz się kisić w tym środowisku, wrzucając na kompilator, który nie ma nic do rzeczy. Tylko że to już twój błąd i to podwójny (używanie tego środowiska i narzekanie na kompilator a nie środowisko).

Tyle co sam posiedziałem przy debuggerze i popatrzyłem co jak się robi to wiem, bo poradnika nigdzie nie znalazłem żadnego.

No zobacz że do Lazarusa jest tutorial po angielsku, a jeżeli chcesz po polsku to możesz używać tych do Delphi które jest podobne.

0
pelsta napisał(a)

To ty sądzisz że FileMode jest źle ustawione. Ja tego nie napisałem.

Nie wmawiaj mi tego, czemu sam zaprzeczam. Przecież wyraźnie napisałem że niektórzy mogą założyć że chodzi o filemode. Nie rozumiem po co bezsensownie wmawiasz mi to czego nie uważam. Skoro nie umiesz czytać to nie ustosunkowuj się do moich wypowiedzi, będzie łatwiejsze niż tłumaczenie tobie 10 razy co napisałem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1