Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[Pascal] Wczytywanie kilku plików tekstowych.

sorell 10 Maj 2010 16:48 2750 22
  • #1 10 Maj 2010 16:48
    sorell
    Poziom 8  

    Witam. Mam za zadanie napisanie programu, który po wczytaniu utworzonego pliku tekstowego odpowiednio z edytuje tekst. Program ma również wczytywać automatycznie pliki z danego katalogu. Dokładnie chodzi o to, że w katalogu jest przykładowo 5 plików tekstowych i chce żeby te pliki zostały z edytowane, każde w ten sam sposób, ale nie chce za każdym razem wpisywać i zmieniać ścieżki do danego pliku, tylko żeby program sam wybierał plik z katalogu i go edytował i wrzucił zmieniony plik do innego katalogu. Tworzone pliki maja ten sam początek lecz są z datą która się zmienia. Część która edytuje mam już gotową tylko zostało właśnie zrobienie tego co opisałem wyżej. Czy jest coś takiego możliwe ??

    0 22
  • #2 10 Maj 2010 16:57
    arnoldziq
    Moderator Programowanie

    Ścieżkę, z której uruchamiasz plik exe, można pobrać z ParamStr(0). Nie jest to jednak konieczne, ponieważ program będzie przeważnie rozpoczynał działanie w katalogu w którym się znajduje.
    Pliki TXT wyszukujesz w tym katalogu, jak i w każdym innym, instrukcjami FindFirst oraz FindNext.

    0
  • #3 10 Maj 2010 17:25
    sorell
    Poziom 8  

    Możesz mi podać, co jest potrzebne do funkcji i jak mniej więcej jak to ma wyglądać.

    0
  • #4 10 Maj 2010 17:35
    arnoldziq
    Moderator Programowanie

    sorell napisał:
    Możesz mi podać, co jest potrzebne do funkcji i jak mniej więcej jak to ma wyglądać.

    Ścieżkę, z której uruchamiasz plik exe, można pobrać z ParamStr(0). Nie jest to jednak konieczne, ponieważ program będzie przeważnie rozpoczynał działanie w katalogu w którym się znajduje.
    Pliki TXT wyszukujesz w tym katalogu, jak i w każdym innym, instrukcjami FindFirst oraz FindNext.

    0
  • #5 11 Maj 2010 09:00
    sorell
    Poziom 8  

    Popatrzalem troche nad funkcją FindFirst i mam mały problem. Gdyż jak mam

    FindFirst('*.txt',AnyFile,Dirinfo);
    (nie wiem czy jest to dobrze zadeklarowane)

    nie wiem jak pozniej sie odwolac do w procedurze assign jak ma to wyglądać, bo nie wiem jaka jest ścieżka lub plik. Czy wystarczy jakbym napisał tylko
    assign(plik,'*.txt'); ??

    Czy należy to jakoś inaczej. Nigdy nie używałem tej funkcji i poraz pierwszy mam z nią do czynienia i nie wiem jak się nią obsługiwać. Jak by ktoś mógł pokazać jakiś przykład to było by miło.

    0
  • #6 11 Maj 2010 10:08
    arnoldziq
    Moderator Programowanie

    Spróbuj uruchomić taki kod :

    Code:
    program pliki_TXT;
    
    uses dos,crt;
    var
     SRC : SearchRec;
    begin
     clrscr;
     FindFirst('*.txt',Archive,SRC);
     while DOSerror=0 do
      begin
       writeln('nazwa pliku = ',SRC.name);
       FindNext(SRC);
      end;
    end.

    0
  • #7 11 Maj 2010 10:20
    sorell
    Poziom 8  

    arnoldziq napisał:
    Spróbuj uruchomić taki kod :
    Code:
    program pliki_TXT;
    
    uses dos,crt;
    var
     SRC : SearchRec;
    begin
     clrscr;
     FindFirst('*.txt',Archive,SRC);
     while DOSerror=0 do
      begin
       writeln('nazwa pliku = ',SRC.name);
       FindNext(SRC);
      end;
    end.


    Kod sie kompiluje i uruchamia (nic się nierobi nie tylko mruga ogienko), ale widze że chyba taak ma byc tylko nie wiem własnie jak w pasowac ten kod do mojego programu:

    Code:

    writeln('Podaj sciezke do pliku pierwszego(podaj z rozszerzeniem)');
    readln(sciezka1);
    writeln('Podaj sciezke do 1 pliku');
    readln(sciezka2);
    writeln('Podaj sciezke do pliku koncowego');
    readln(sciezka3);


    assign(plik,sciezka1);
    reset(plik);

    while not eof(plik) do
      begin
        read(plik,s);
       if (s<> #9)and(s<> #32)and(s<>#3)and(s<>#2)and(s<>#13)and(s<>#10)and(s<>#45)and(s<>#31)and(s<>#95) then
         begin
           zn[i]:=s;
           i:=i+1;

           end;


      end;
    k:=0;
    for j:=0 to i do
      begin
      {
      write(zn[j]);}
      k:=k+1;
      write(#220);



      end;


    assign(plik1,sciezka2); {zapisanie tablicy do nowego pliku}
    rewrite(plik1);

    for j:=0 to i do
    begin

       write(plik1,zn[j]);


    end;

    close(plik1);
    close(plik);


    I własnie nie ma być tego że wczytuje ścieżki tylko poprostu znajduje sam pliki w katalogu wczytuje i konwertuje je.


    Edit.

    Ok. Poradziłem sobie z tym wczytuje plik i robi co ma robić ale robi to tylko z jednym plikiem w folderze a chcialbym zeby robil to na kilku. Jakies rady ?

    0
  • Pomocny post
    #8 11 Maj 2010 11:07
    arnoldziq
    Moderator Programowanie

    Strasznie skomplikowany ten twój program. Trudno się połapać o co chodzi.
    Kompletnie bez sensu używasz tablicy do zapamiętania kolejnych znaków czytanych z pliku.

    Code:
    program pliki_TXT;
    
    uses dos,crt;
    const
     opusc = [#9,#32,#3,#2,#13,#10,#45,#31,#95];
    var
     SRC : SearchRec;
     ile : integer;
    {****************************************}
    procedure zmien_plik(nazwa : string);
    var
     plik1,plik2 : file of char;
     znak : char;
     nazwa2 : string;
    begin
     ile:=ile+1;
     str(ile,nazwa2);
     nazwa2:='plik'+nazwa2+'.txt';
     writeln(' zmieniam plik ',nazwa,', nowa zawartosc w pliku : ',nazwa2);

     assign(plik1,nazwa);
     reset(plik1);
     assign(plik2,nazwa2);
     {$I-}
     rewrite(plik2);
     {$I+}
     while not EOF(plik1) do
      begin
       read(plik1,znak);
       if not (znak in opusc) then
       write(plik2,znak);
      end;
     close(plik2);
     close(plik1);
     writeln(' Zmiany wykonane.');
    end;
    {****************************************}
    begin
     clrscr;
     ile:=0;
     FindFirst('*.txt',Archive,SRC);
     while DOSerror=0 do
      begin
       zmien_plik(SRC.name);
       FindNext(SRC);
      end;
      writeln(' Koniec programu. Znaleziono i zmieniono ',ile,' plikow.');
    end.


    W/w kod powinien robić dokładnie to samo, ale dla wszystkich plików TXT, znajdujących się w tym samym katalogu co plik EXE.

    0
  • #9 11 Maj 2010 11:19
    sorell
    Poziom 8  

    Wielkie dzieki działa ładnie. Ale jak widze żle zrobilem, że nie dałem całego programu :P Ponieważ jest tworzony jescze jeden plik ostateczny

    Code:

    i:=0;
    assign(plik1,'2'+SRC.name);
      reset(plik1);

    assign(plik2,'3'+SRC.name);
       rewrite(plik2);
       while(not eof(plik1)) do
               begin
                 read(plik1,s);
                 inc(i);
                 if i mod 29=0 then writeln(plik2,s)
                 else write(plik2,s);
    end;
    close(plik2);
    close(plik1);


    Tu chodzi o to ze wczytuje wczesniej wczytany poprawiony plik i daje przejscie do nastepnej lini w odpowiednim momencie. Moim 'skomplikowanym' sposobem dziala to dobrze. Tylko teraz musze to jakos w komponowac w twój kod.

    Code:

    procedure enter(nazwa2 :string);
    var
       plik2,plik3 :file of char;
       znak: char;
       nazwa3 : string;
       i: integer;
    begin
     ile:=ile+1;
     str(ile,nazwa2);
     nazwa2:='plik'+nazwa3+'.txt';
     writeln(' zmieniam plik ',nazwa2,', nowa zawartosc w pliku : ',nazwa3);

     assign(plik2,nazwa2);
     reset(plik2);
     assign(plik3,nazwa3);
     {$I-}
     rewrite(plik3);
     {$I+}
     while not EOF(plik2) do
          begin
               read(plik2,znak);
               inc(i);
               if i mod 29=0 then
               begin
               writeln;
               write(plik3,znak);
               end;
          end;
     close(plik3);
     close(plik2);
     writeln(' Zmiany wykonane.');
     end;


    Moje wypociny :P Ale nie działa bardzo możliwe, że jest coś nie tak. Troche cięzko zrozumieć tok myślenie innej osoby ;p

    0
  • #10 11 Maj 2010 11:49
    arnoldziq
    Moderator Programowanie

    To w tym miejscu :

    Code:
    if not (znak in opusc) then
    
       write(plik2,znak);

    Daj zliczanie znaków i po zadanej liczbie dodawaj koniec linii.
    Coś w tym stylu :
    Code:
    if not (znak in opusc) then
    
      begin
       write(plik2,znak);
       inc(licznik);
       if licznik >=29 then
         begin   
          writeln(plik2,'');
          licznik:=0;
         end;
      end;

    0
  • #11 11 Maj 2010 11:59
    sorell
    Poziom 8  

    Występuje taki bład "Error: Can't use readln or writeln on typed file" w miejscu gdzie ma przejść do nastepnej linii.

    0
  • #12 11 Maj 2010 12:03
    arnoldziq
    Moderator Programowanie

    Code:
    writeln(plik,'');
    To to samo co :
    Code:
    write(plik,#10);write(plik,#13);

    0
  • #13 11 Maj 2010 12:27
    sorell
    Poziom 8  

    Wielkie dzięki program działa jak narależy. Jeszcze jak zrobić zeby usuwał jak napotka takie wiersz (90 rows affected), czy da się zrobic tak, żeby usuną cały na ten nawias ale zawartość jest różna, znaczy się liczba się zmienia. Dało by się to zrobic deletem normalnie ??

    0
  • #14 11 Maj 2010 12:40
    arnoldziq
    Moderator Programowanie

    Musiałbyś przeglądać, przy czytaniu, cały tekst linia po linii, i sprawdzać czy odczytany tekst zawiera oczekiwany ciąg znaków. Trochę się trzeba nad tym "namordować", ale nie powinno być problemów.
    1. Plik jako TEXT
    2. Czytasz linię tekstu do zmiennej.
    3. Sprawdzasz czy występuje interesujący Cię ciąg znaków np. za pomocą POS.
    4. Jeżeli tak, to wyodrębniasz interesujący Cię numer/liczbę.
    5. Czytasz następną linię ... itd. aż do końca pliku -> pkt 3.

    0
  • #15 11 Maj 2010 12:44
    sorell
    Poziom 8  

    Tylko właśnie o to chodzi, że ten ciąg znakow nie jest za każdym razem taki sam zmienia sie sie liczba wew. i zaczyna się i konczy nawiasami. Da się tak zrobić żeby wląsnie usuwało od nawiasu do nawiasu żeby z (90 rows affected) nie było nic. Możliwe że trzeba właśnie popracować z funkcja delete i pos, ale nie wiem jak napisać, gdy spotkasz '(' usuwaj wszystkie znaki,aż nie napotkasz ')'. Bo mógłbym napisać jeżeli znak jest '(' rób break, ale nawias może znajdować się w środku tekstu i nie bedzie wszystkiego

    0
  • Pomocny post
    #16 11 Maj 2010 14:33
    arnoldziq
    Moderator Programowanie

    Weźmy np. taką linię :" (123 rows affected)".
    Musisz ustalić jaki element będzie niezmienny. Np. rows affected. Nazwijmy ten niezmienny ciąg znaków, po prostu, znacznikiem.
    Pobierasz całą linię tekstu. Sprawdzasz czy znajduje się w tej linii znacznik. Wiemy, że ten ciąg jest poprzedzony jakąś cyfrą oraz nawiasem.
    Funkcja POS, zwróci Ci jaką pozycję w tej linii ma znacznik, w tym przypadku 6.
    Usuwasz z linii tekstu wszystko od tej pozycji -1 (6-1=5), do końca linii.
    Pozostaje " (123". Dokładnie 5 znaków.
    Teraz sprawdzasz pozycję nawiasu "(" i w to miejsce wstawiasz spację.
    Pozostaje " 123".
    A taki ciąg znaków możesz spokojnie "przepuścić" przez procedurę VAL, która zwróci Ci wartość liczbową.
    Nie musisz przejmować się spacjami poprzedzającymi liczbę. Tylko spacje znajdujące się za liczbą, powodują błędne działanie procedury VAL.

    0
  • #17 12 Maj 2010 09:46
    sorell
    Poziom 8  

    Napisałęm takie coś żeby znalazło mi ten stały wyraz i go usuneło nie wiem jak przypisać to do zmiennej chciałem zrobić tak:

    znacznik = ['rowsaffected']

    ale pojawiał sie błąd "Error: Type conflict between set elements"

    wiec napisałem normalnie w warunku który wygląda mniej wiecej tak :

    Code:

    if pos('rowsaffected',znak)>0 then
        delete(znak,pos('rowsaffected',znak),12);


    ale nie działa to jednak nie wiem dlaczego. Występuje taki bład

    "Error: Can't determine which overloaded function to call"

    Warunek znalazłęm gdzies na internecie wydawało mi się że może sie przydać.

    arnoldziq napisał:

    Teraz sprawdzasz pozycję nawiasu "(" i w to miejsce wstawiasz spację.
    Pozostaje " 123".
    A taki ciąg znaków możesz spokojnie "przepuścić" przez procedurę VAL, która zwróci Ci wartość liczbową.
    Nie musisz przejmować się spacjami poprzedzającymi liczbę. Tylko spacje znajdujące się za liczbą, powodują błędne działanie procedury VAL.


    Tu może być problem jak zostana same liczby, ponieważ każdy wiersz wygląda mniej więcej tak "GEHXX022010043005545208522968" i jak zostana liczby to nie zleja sie czasem z tymi??

    0
  • #18 12 Maj 2010 10:12
    arnoldziq
    Moderator Programowanie

    Dobra. Wracamy do punktu wyjścia, bo zaczyna się w ten temat wkradać chaos.
    Proszę podać dokładny tekst linii którą chcesz "operować", bo ja już się pogubiłem.
    Najlepiej podaj przykłady kilku, różnych, tego typu linii.
    Wklej tu, po prostu, kawałek pliku tekstowego, na którym musisz operować.

    0
  • #19 12 Maj 2010 10:17
    sorell
    Poziom 8  

    Code:

    KOMXX012010043005320008523334                                                                                           
     GEHXX012010043005320108523334                                                                                                 
     KOMXX012010043005320008885280                                                                                                 
     GEHXX012010043005320108885280                                                                                                 
     KOMXX012010043005330007404899                                                                                                 
     GEHXX012010043005330107404899                                                                                                 
     KOMXX012010043005340007394717                                                                                                 
     GEHXX012010043005340107394717                                                                                                 
     KOMXX012010043005340007396785                                                                                                                                                                                                             
    (158 rows affected)


    I to własnie miało usuwać przestrzen pomiedzy tymi tekstami i przed (tutaj nie widac) I zeby koncowy wynik wygladal tak:

    Code:

    KOMXX012010043005320008523334
    GEHXX012010043005320108523334
    KOMXX012010043005320008885280
    GEHXX012010043005320108885280
    KOMXX012010043005330007404899
    GEHXX012010043005330107404899
    KOMXX012010043005340007394717
    GEHXX012010043005340107394717
    KOMXX012010043005340007396785
    GEHXX012010043005340107396785
    KOMXX012010043005360007396520
    GEHXX012010043005360107396520
    KOMXX012010043005400007397850
    GEHXX012010043005400107397850
    KOMXX012010043005410008524191
    GEHXX012010043005410108524191
    KOMXX012010043005410008897028
    GEHXX012010043005410108897028
    KOMXX012010043005410008972762
    (158 rows affected)


    Ten nawias występuje w różnych miejscach, bo ten plik jest tworzony przez inny program. Dorzucam cały plik.

    0
  • #20 12 Maj 2010 11:02
    arnoldziq
    Moderator Programowanie

    No to trochę się rozjaśniło :)

    Musisz podejść do tego problemu trochę inaczej.
    Na twoim miejscu, najpierw usuwałbym te niepotrzebne line, a dopiero potem zajął się usuwaniem zbędnych linii.
    Poza tym, jeżeli twoje "dane" (te ciągi znaków), zawsze maja taką samą długość, to nie ma sensu zabawanie się czytaniem tego tekstu znak po znaku. Trzeba czytać całe linie i usuwać zbędne, te które są za krótkie ( np. puste ) oraz te zawierające np. nawias "(".
    To dramatycznie uprości cały program.

    0
  • #21 12 Maj 2010 11:28
    sorell
    Poziom 8  

    Nie wiem, czy juz by mi się chciało znowu głowić na tym żeby zrobić inna techniką, bo itak juz się nad tym głowie długi czas. Wydaje mi się, że wystarczy zrobić tylko tego delete. Ważne jest tylko żeby to działało.

    Code:

    if pos(s,znak)>0 then
           delete(s,pos(s,znak),12);
           end;


    dla S przypisałem 'rowsaffected'.

    I jeszcze mi się wydaje że na długości wiersza mogło by to nie wyjśc ponieważ przeryw miedzy tekstami to jest przestrzeń tak jakby biała duza spacja, jak sie chce to usunac to sie zaznacza kilka wierszy nie można usunąc normalnie jak spacje. Może widziałes to w pliku co zamieścilem. To jest tak, że jak sie sformatuje to z 1,2MB pliku tekstowego robi sie 5kB.

    Więc chyba lepiej pomyśleć jakoś nad tym deletem :P

    0
  • Pomocny post
    #22 12 Maj 2010 11:29
    arnoldziq
    Moderator Programowanie

    Spróbuj czegoś takiego :

    Code:
    program pliki_TXT;
    
    uses dos,crt;
    var
     SRC : SearchRec;
     ile : integer;
    {****************************************}
    procedure TRIM(var src : string);
    begin
     while pos(' ',src)<>0 do
      delete(src,pos(' ',src),1);
    end;
    {****************************************}
    procedure zmien_plik(nazwa : string);
    var
     plik1,plik2 : text;
     linja : string;
     nazwa2 : string;
    begin
     ile:=ile+1;
     str(ile,nazwa2);
     nazwa2:='plik'+nazwa2+'.txt';
     writeln(' zmieniam plik ',nazwa,', nowa zawartosc w pliku : ',nazwa2);

     assign(plik1,nazwa);
     reset(plik1);
     assign(plik2,nazwa2);
     {$I-}
     rewrite(plik2);
     {$I+}
     while not EOF(plik1) do
      begin
       readln(plik1,linja);
       TRIM(linja); {usuwanie zbednych spacji}
       if (length(linja)>5) and (pos('(',linja)=0) then
       write(plik2,linja);
      end;
     close(plik2);
     close(plik1);
     writeln(' Zmiany wykonane.');
    end;
    {****************************************}
    begin
     clrscr;
     ile:=0;
     FindFirst('*.txt',Archive,SRC);
     while DOSerror=0 do
      begin
       zmien_plik(SRC.name);
       FindNext(SRC);
      end;
      writeln(' Koniec programu. Znaleziono i zmieniono ',ile,' plikow.');
    end.

    0
  • #23 12 Maj 2010 11:42
    sorell
    Poziom 8  

    Ok, szybki jesteś :D Dzieki. Nie ma przestrzeni spacji, ani znaków ale znowu nie ma przejść
    Jak daje:

    Code:

    if length(linja)=29 then
          begin
          writeln(plik2,#13);
          write(plik2,#10);
          end;


    dałem też writeln(plik2,linja), ale też nie działa.
    Edit.

    Ok jednak działa tak jak zrobiłem :P nie wiem czemu ale jest ;] Wielkie dzięki!!

    0