# Python 8 (obsługa plików, json)

# Python 8 (obsługa plików, json)
Photo by Maksym Kaharlytskyi / Unsplash

Systemy plików:

  • NTFS (New Technology File System) – domyślny system plików w Windows.
  • ext4 (Fourth Extended File System) – najczęściej używany system plików w Linuksie; inne przykładowe systemy w Linux: XFS, Btrfs.
  • APFS (Apple File System) – nowoczesny system plików Apple, używany w macOS i iOS.

Ścieżka do pliku (ang. file path) to ciąg znaków, który wskazuje dokładne położenie pliku lub folderu w strukturze systemu plików na dysku komputera. Składa się z nazw kolejnych katalogów prowadzących do danego pliku.

  • Ścieżka bezwzględna (absolutna) – zawiera pełną drogę od katalogu głównego (rootu) do pliku.

ścieżka w Windows: C:\Uzytkownicy\Natalia\Dokumenty\raport.docx

ścieżka w Linux: /home/natalia/dokumenty/raport.docx

  • Ścieżka względna (relatywna) – wskazuje położenie pliku względem bieżącej lokalizacji, np. Z użyciem .. (z katalogu dokumenty do pliku w zdjęcia): ../zdjęcia/wakacje.jp
Znaki specjalne
  • . – oznacza bieżący katalog
  • .. – oznacza katalog nadrzędny (o jeden poziom wyżej)

Obsługa plików w Pythonie

  • otwieranie plików (tryb odczytu)
with open("nowy.txt", "r") as plik:
    print(plik.read())

# otwieranie z with aby plik był domykany na koniec pracy

# Domyślnie Python otwiera pliki w trybie do odczytu ("r") - podczas pracy w nim można jedynie odczytać zawartość pliku, nie można nic dodać

# na wczytanym obiekcie jest użyta metoda .read() umożliwiająca odczytanie całej zawartości jako ciąg znaków (string).
  • zapisywanie
with open("nowy.txt", "w") as plik:
    plik.write("Ala ma kota.\nOla ma chomika.")

# Parametr "w" jest dodawany do funkcji open, w nawiasach okrągłych, obok nazwy pliku, który chcemy otworzyć.

# WAŻNE!!! - w tym trybie istniejąca zawartość pliku zostanie nadpisana(!).

# Jeśli chcemy dopisać coś do końca pliku trzeba użyć trybu "a" (od append):

with open("nowy.txt", "a") as plik:
    plik.write("\nKasia ma psa.")

Tryb binarny i tekstowy

Domyślnie Python traktuje otwarte pliki jako tekst. Czasami zachodzi jednak potrzeba otwarcia ich w trybie binarnym (np. przy większości formatów obrazków) - wystarczy dodać literkę "b" do trybu.

Poza trybem r służącym do odczytu,w do napisania i a do dopisania Python oferuje nam różne kombinacje trybów.

tryb opis
r odczyt
r+ odczyt i zapis, błąd jeśli plik nie istnieje
rb odczyt w trybie binarnym
rb+ odczyt i zapis w trybie binarnym, błąd gdy plik nie istnieje
w zapis, nadpisuje zawartość, tworzy plik gdy nie istnieje
w+ odczyt i zapis, nadpisuje zawartość, tworzy plik gdy nie istnieje
wb zapis w trybie binarnym, nadpisuje zawartość, tworzy plik gdy nie istnieje
wb+ odczyt zapis w trybie binarnym, nadpisuje zawartość, tworzy plik gdy nie istnieje
a dopisanie zawartości, tworzy plik gdy nie istnieje
a+ odczyt i dopisanie zawartości, tworzy plik gdy nie istnieje
ab dopisanie w trybie binarnym, tworzy plik gdy nie istnieje
ab+ odczyt i dopisanie w trybie binarnym, tworzy plik gdy nie istnieje

Pliki Json

(JavaScript Object Notation) to lekki format wymiany danych, bardzo często używany do przechowywania i przesyłania informacji pomiędzy aplikacjami, np. w komunikacji klient–serwer.

  • Tekstowy format danych — zawartość to zwykły tekst, który można otworzyć w dowolnym edytorze.
  • Struktura oparta na parach klucz–wartość, podobna do słowników w Pythonie czy obiektów w JavaScripcie.
  • Łatwy do odczytu przez człowieka i maszynę.
  • Niezależny od języka programowania — można go używać w Pythonie, C#, Java, JavaScript, PHP itd.
# Typowy plik json
{
  "imie": "Jan",
  "wiek": 30,
  "czy_student": false,
  "hobby": ["sport", "muzyka", "programowanie"],
  "adres": {
    "ulica": "Kwiatowa 5",
    "miasto": "Kraków"
  }
}
### Zapis słownika w pliku json

import json

slownik = {
    "Jan": ["555333222", "jakis opis"],
    "Maria": ["555667778", "kolejny opis"],
    "Franek": ["789123456", "znowu opis"],
    "Ala": ["555666222", "kolejny opis"],
    "AAA": None
}

with open("jsonsave.json","w") as plik:
    json.dump(slownik, plik, indent=4)

# kod zapisze słownik slownik do pliku jsonsave.json w formacie JSON, z wcięciem (indent=4) dla czytelności. Utworzy plik json w trybie write.

# Klucz "AAA" będzie miał wartość null w pliku (bo None w Pythonie konwertuje się na null w JSON).

### Wczytanie pliku json

with open("slowniczek.json", "r", encoding="utf-8") as plik:
    zawartosc = json.load(plik)

Sprawdzenie czy plik istnieje

import json
import os

if os.path.exists("plik.json"):
    with open("plik.jason") as plikk:
    #itd.

Aplikacja kontakty

import json
import os

kontakty = {"Alice" : "[email protected]",
            "Bob" : "[email protected]"
            }


def zapisz_kontakty():
    with open("kontakty.json", "w", encoding="utf-8") as plik:
        json.dump(kontakty,
                  plik,
                  indent = 4,
                  sort_keys=True,
                  ensure_ascii = False)
        
def wczytywanie_kontaktow():
    if os.path.exists("kontakty.json"):
        with open("kontakty.json", "r", encoding = "utf-8") as plik:
            lista_kontaktow = json.load(plik)
            kontakty.clear()
            kontakty.update(lista_kontaktow)


wczytywanie_kontaktow()


def nowy_kontakt():
    pseudonim = input("Podaj pseudonim: ").strip()
    if pseudonim in kontakty.keys():
        print("Taki kontakt już istnieje!")
    else:
        dane = input("Podaj e-mail): ").strip()
        kontakty[pseudonim] = dane
        zapisz_kontakty()
        print("Dodano nowy kontakt")
        print("***************")

def aktualizacja_kontaktu():
    wybrany_kontakt = input("Wybierz imię/pseudonim do modyfikacji: ").strip()
    if wybrany_kontakt in kontakty:
        kontakty[wybrany_kontakt] = input("Wprowadź nowe dane kontaktowe: ").strip()
        zapisz_kontakty()
    else:
        print("Nie ma takiego kontaktu!")

def usuwanie_kontaktow():
    pseudonimdelete = input("Wprowadź imię/pseudonim kontaktu do usunięcia: ").strip()
    if pseudonimdelete in kontakty.keys():
        kontakty.pop(pseudonimdelete) # lub del kontakty[pseudonimdelete]
        zapisz_kontakty()
        print("Kontakt usunięty")
        print("***************")
    else:
        print("Nie ma takiej pozycji w kontaktach")
        print("***************")


def wyswietlanie_kontaktow():
    for imie, dane in kontakty.items():
        print(f"{imie}: {dane}")
    print("***************")

def wyswietlenie_wybranego():
    wybrany_kontakt = input("Podaj imię/pseudonim kontaktu: ").strip()
    if wybrany_kontakt in kontakty:
        print(wybrany_kontakt)
        print(kontakty[wybrany_kontakt])
        print("***************")


while True:
    print("Książka kontaktowa:")
    print("Wybierz operację:")
    print("1 - dodanie wpisu")
    print("2 - aktualizacja wpisu")
    print("3 - usunięcie wpisu")
    print("4 - wydruk wszystkich kontaktów")
    print("5 - wydruk konretntego kontaktu")
    print("6 - koniec programu")

    wybor = input("Podaj kod operacji: ").strip()

    if wybor == "1":
        print("1")
        nowy_kontakt()
    elif wybor == "2":
        print("2")
        aktualizacja_kontaktu()
    elif wybor == "3":
        print("3")
        usuwanie_kontaktow()
    elif wybor == "4":
        print("4")
        wyswietlanie_kontaktow()
    elif wybor == "5":
        print("5")
        wyswietlenie_wybranego()
    elif wybor == "6":
        print("Koniec programu")
        break
    else:
        print("Nie ma opcji o podanym kodzie.")