200/736

Práce se soubory -- příklad

Obsah:

  1. Zadání
  2. Reference
  3. Kostra zdrojového kódu
  4. Hlavní programová smyčka
  5. Práce se souborem
  6. Převod na malá písmena
  7. Nahrazení jednoho znaku jiným
  8. Statistika souboru
  9. Generování náhodného textu

Zadání

Vytvořte aplikaci, která čte uživatelem zadaný soubor a zapisuje do dalšího uživatelem zadaného souboru. Aplikace provádí následující akce:

Aplikace se bude ovládat interaktivně pomocí jednoduchého menu.

Příklad činnosti programu:

    1) Převod na malá písmena
    2) Nahrazení znaků
    3) Statistika souboru 
    4) Generování náhodného textu
    5) Konec
    1-5> 1
    >>> zadej jmého vstupního souboru: text
    >>> zadej jmého výtupního souboru: /dev/stdout
    python 

    python je dynamický objektově orientovaný skriptovací
    programovací jazyk, který v roce 1991[1] navrhl guido van rossum.
    python je vyvíjen jako open source projekt, který zdarma nabízí
    instalační balíky pro většinu běžných platforem (unix,
    windows, mac os); ve většině distribucí systému linux je python
    součástí základní instalace.

    mimo jiné je v něm implementován aplikační server zope, instalátor a
    většina konfiguračních nástrojů linuxové distribuce firmy red hat.
    -----------------------------------------------------------------------
    1) Převod na malá písmena
    2) Nahrazení znaků
    3) Statistika souboru 
    4) Generování náhodného textu
    5) Konec
    1-5> 2
    >>> zadej znak, který se má nahradit: a
    >>> zadej znak, kterým se má nahradit: @
    >>> zadej jmého vstupního souboru: text
    >>> zadej jmého výtupního souboru: /dev/stdout
    Python 

    Python je dyn@mický objektově orientov@ný skriptov@cí
    progr@mov@cí j@zyk, který v roce 1991[1] n@vrhl Guido v@n Rossum.
    Python je vyvíjen j@ko open source projekt, který zd@rm@ n@bízí
    inst@l@ční b@líky pro většinu běžných pl@tforem (Unix,
    Windows, M@c OS); ve většině distribucí systému Linux je Python
    součástí zákl@dní inst@l@ce.

    Mimo jiné je v něm implementován @plik@ční server Zope, inst@látor @
    většin@ konfigur@čních nástrojů Linuxové distribuce firmy Red H@t.
    -----------------------------------------------------------------------
    1) Převod na malá písmena
    2) Nahrazení znaků
    3) Statistika souboru 
    4) Generování náhodného textu
    5) Konec
    1-5> 3
    >>> zadej jmého vstupního souboru: text
    A      27 ********************************
    Á       5 ******
    B       6 *******
    C      11 *************
    Č       4 ****
    D       8 *********
    E      23 ***************************
    É       3 ***
    Ě       7 ********
    F       3 ***
    G       3 ***
    H       8 *********
    I      24 *****************************
    Í      12 **************
    J      11 *************
    K      12 **************
    L      11 *************
    M      13 ***************
    N      33 ****************************************
    O      30 ************************************
    P      13 ***************
    R      23 ***************************
    S      17 ********************
    Š       3 ***
    T      25 ******************************
    U      12 **************
    Ů       1 *
    V      17 ********************
    W       2 **
    X       3 ***
    Y      10 ************
    Ý       5 ******
    Z       5 ******
    Ž       1 *
    1       3 ***
    9       2 **
    řádků: 11, slov: 66, znaků: 466
    -----------------------------------------------------------------------
    1) Převod na malá písmena
    2) Nahrazení znaků
    3) Statistika souboru 
    4) Generování náhodného textu
    5) Konec
    1-5> 4
    >>> zadej jmého výtupního souboru: /dev/stdout
    >>> zadej počet slov: 20
    opa ulide y be p uwegovy e kutuve pidyfel apugyve r e utuxoli mypacogo ykukyw
    orobusij edocy w vyjig ehotyzi 

    -----------------------------------------------------------------------
    1) Převod na malá písmena
    2) Nahrazení znaků
    3) Statistika souboru 
    4) Generování náhodného textu
    5) Konec
    1-5> 5

`--> stáhnout

Reference

Kostra zdrojového kódu

#!/usr/bin/python
# -*- coding: utf8 -*-

from Tkinter import *

##################################################
### Definice funkcí 


##################################################
### Hlavní programová smyčka


##################################################

`--> stáhnout

Hlavní programová smyčka

Jádrem programu bude smyčka ve které se uživatele stále dokola práme, co se má udělat:

while True:
    print "1) Převod na malá písmena"
    print "2) Nahrazení znaků"
    print "3) Statistika souboru "
    print "4) Generování náhodného textu"
    print "5) Konec"
    try:
        volba = int(raw_input("1-5> "))
        if volba == 1:
            prevod()
        elif volba == 2: 
            nahrazeni()
        elif volba == 3: 
            statistika()
        elif volba == 4:
            nahodnyText(40)
        elif volba == 5: 
            exit(0)
        else:
            print "\n>>>> Zadej číslo od 1 do 5\n"
    except ValueError: 
        print "\n>>>> Zadej číslo od 1 do 5\n"
    except EOFError: 
        exit(0)

`--> stáhnout

Teď už jen stačí napsat funkce pro obsluhu jednotlivých "akcí" -- tedy prevod(), nahrazeni(), statistika() a nahodnyText().

Práce se souborem

Soubor je nejprve třeba otevřít. To se děje pomocí funkce open().

ovladac = open('cesta/k/souboru', mod)

`--> stáhnout

Kde mod je buď "r" pro čtení, "w" pro zápis nebo "a" pro přidání do souboru. V režimu pro zápis je souboru vždy smazán (pokud existuje) a vytvořen nový, prázdný. V režimu pro přidání se souboru otevře pro zápis, ale jeho obsah se nesmaže a ukazatel se nastaví na konec souboru.

ovladac je objekt, přes který se se souborem komunikuje:

ovladac.read(pocet)
přečte zadaný počet byte ze souboru.
ovladac.readline()
přečte řádek ze souboru.
ovladac.readlines()
načte celý soubor do seznamu, v každé položce je jeden řádek.

Pokud dojdeme na konec souboru vrátí tyto metody vždy prázdný řetězec, tedy ''.

ovladac.write(obsah)
zapíše obsah do souboru
ovladac.writelines(seznam)
zapíše do souboru seznam, v každé položce jeden řádek -- řádky musí být včetně znaku '\n'.
ovladac.close()
uzavře soubor a tím ukončí práci s ním.

Převod na malá písmena

Zde pracujeme simultánně s dvěma otevřenými soubory jeden (vstupní) je otevřen pro čtení, druhý (výstupní) je otevřen pro zápis. Vždy načteme řádek, pomocí metody .lower() převedeme na malá písmena a zapíšeme do výstupního souboru.

O ošetření chyb se postará blok try: except.

def prevod():
    """Funkce převede všechna písmena v soboru na malá"""
    try:
        # otevřu:
        inName = raw_input(">>> zadej jmého vstupního souboru: ")
        inFile = open(inName,"r")
        outName = raw_input(">>> zadej jmého výtupního souboru: ")
        outFile = open(outName,"w")
        # čtu do konce souboru
        while True:
            # čtu:
            radek = inFile.readline()
            # na konci souboru mi funkce vrátí prázdný řetězec 
            if radek == '':
                break
            # zapisuji
#            radek = radek.decode('utf-8')
#            radek = radek.upper()
#            radek = radek.encode('utf-8')
            outFile.write(radek.decode('utf-8').upper().encode('utf-8'))
            outFile.write(radek.decode('utf-8').lower().encode('utf-8'))

        # uzavřu soubory
        inFile.close()
        outFile.close()
    except IOError:
        print "\nERROR > Něco je špatně:"
        print "ERROR > zkontroluj si jméno souboru a přístupová práva\n"

`--> stáhnout

Pokud požadujete, aby fungovala správně i čeština je nutné následující:

  1. importujte si modul locale
  2. před převodem na malá písmena převeďte řetězec do Unicode a poté opět zpět do příslušné znakové sady.

Nahrazení jednoho znaku jiným

Zde je vše stejné jako u převodu na malá písmena, takže uvedu jen to co se liší. Opět jsou otevřené dva soubory najednou -- jeden pro čtení, druhý pro zápis. Jen se uživatel musíme navíc zeptat na znak nahrazovaný a nahrazující.

Nabízím zde řešení, kdy se soubor zpracovává po znacích.

...
...
    while True:
        # čtu:
        znak = inFile.read(1)
        # na konci souboru mi funkce vrátí prázdný řetězec 
        if znak == '':
            break
        # zapisuji
        if znak == znakStary:
            outFile.write(znakNovy)
        else:
            outFile.write(znak)
...
...

`--> stáhnout

To je ale hodně nevýhodné při práci s českým textem ve více-bytovém kódování jak o je třeba UTF-8. V tomto případě se jeví se vhodnější zpracovávat soubor po řádcích (stejně jako v předchozím případě) a použít na každý řádek metodu str.replace.

...
...
    while True:
        radek = inFile.readline()
        if radek == '':
            break
        outFile.write(radek.decode('utf-8').replace(znakStary,znakNovy).encode('utf-8'))
...
...

`--> stáhnout

Statistika souboru

Statistika souboru vypisuje

  1. počet řádků slov a písmen
  2. počty výskytů jednotlivých znaků

Soubor budeme zpracovávat pořádcích -- to nám umožní počítat řádky a slova.

Dále pak každý řádek zpracujme po jednotlivých znacích. Pro ukládání počtu jednotlivých znaků použijeme [slovník][py_slovnik]. Klíčem budou jednotlivé znaky.

Při výpisu počtu znaků je potom vytvořen jednoduchý bargraf, který počet znaků vizualizuje.

f = open('/dev/stdin', 'r')

pocetRadku = 0
pocetZnaku = 0
pocetSlov = 0

# slovník do kterého ukládám četnosti znaků jednotlivých písmen
# klíčem je vždy písmeno
cetnostZnaku={}

while True:
    radek=f.readline()
    if radek == '':  
        break       # protože jsem došel na konec souboru
    radek = radek.decode('utf-8') # aby se znaky s diakritikou chovali jako písmeno
    pocetRadku = pocetRadku + 1
    delka=len(radek)
    pocetZnaku += delka         
    pocetSlov += len(radek.split()) # řádek rozdělím na slova
    for znak in radek:  # řádek zpracovávám po znacích
        if znak in (' ','\t', '\n' ):
            continue    # bílé znaky přeskoč
        # četnost jednotlivých znaků
        if cetnostZnaku.has_key(znak):
            cetnostZnaku[znak] += 1
        else:
            cetnostZnaku[znak] = 1          

print "----  četnosti znaků    -------------"
for znak in cetnostZnaku.keys():
    pocet = 60 * cetnostZnaku[znak] / max(cetnostZnaku.values())
    graf = '*' * pocet
    print "{0:2s}{1:10} |{2}".format( znak, cetnostZnaku[znak], graf )
print "-------------------------------------"
print "počet řádků:", pocetRadku
print "počet slov:", pocetSlov
print "počet znaků:", pocetZnaku
print "-------------------------------------"

`--> stáhnout

Generování náhodného textu

Při generování náhodného textu požadujeme aby

  1. se střídala souhláska a samohláska
  2. slovo mělo náhodnou délku
  3. slovo začínalo náhodně souhláskou nebo samohláskou

Vytvoříme tedy seznam souhlásek a samohlásek a budeme z nich náhodně na-střídačku vybírat vždy jeden znak. Také náhodně určíme jestli samohlásky/souhlásky jsou sudé/liché (řádek 12 a 14). Celé to provádíme v náhodně dlouhém cyklu čímž zajistíme náhodnou délku slov.

   1 import random
   2 
   3 ...
   4 
   5 def nahodnyText(pocetSlov):
   6     samohlasky = 'aeiyou'
   7     souhlasky ='qwrtpsdfghjklzxcvbnm'
   8 
   9     for i in range(pocetSlov):
  10         #jedno slovo
  11         delkaSlova = random.randint(1,8)
  12         zacatek = random.randint(0,1)  # zacinam samohlaskou nebo souhlaskou?
  13         for i in range(delkaSlova):
  14             if i % 2 == zacatek:       # ztrida se samohlaska a souhlaska
  15                 sys.stdout.write( random.choice(souhlasky) )
  16             else:
  17                 sys.stdout.write( random.choice(samohlasky) )
  18         sys.stdout.write(' ')
  19     sys.stdout.write('\n\n')

`--> stáhnout

| navigace |

Licence Creative Commons Valid XHTML 1.0 Strict Valid CSS! Antispam.er.cz Blog: Tlapicka.net