====== Operacje na plikach ====== * pliki o określonym formacie (csv, dat, PNG, mp3) - funkcje wysokopoziomowe * ''%%load%%'', ''%%save%%'' - wczytywanie i zapis zmiennych Matlaba oraz plików tekstowych o tabelarycznej strukturze * ''%%imread%%'', ''%%imwrite%%'' - pliki grficzne (PNG, JPG, …) * ''%%xlsread%%'', ''%%xlswrite%%'' - arkusze kalkulacyjne Excel * ''%%dlmread%%'', ''%%dlmwrite%%'' - pliki tektowe w tabelarycznej formie z separatorem * ''%%importdata%%'' - wiele formatów (ASCII, csv, jpg, xls, …) * pliki z nieokreśloną strukturą -> operacje I/O niskopoziomowe * ''%%fopen%%'', ''%%fprintf%%'', ''%%fscanf%%'', … ===== Funckje load i save ===== * ''%%save 'nazwa_pliku'%%'' zapisuje wszystkie zminne (całą przestrzeń roboczą) do pliku * ''%%save 'nazwa_pliku', x%%'' zapis zmiennej ''%%x%%'' do pliku * ''%%save 'nazwa_pliku' x --ascii%%'' zapis xmiennej ''%%x%%'' do pliku w postaci tekstowej x = rand(3,5); % zapis do pliku save 'zmienna.mat' x; % odczyt z pliku z = load('zmienna'); disp(z) whos z x scalar structure containing the fields: x = 0.8776665 0.2506873 0.9552747 0.0312580 0.0818354 0.8777180 0.6151687 0.5800066 0.6321469 0.0067620 0.8095648 0.9337047 0.2573228 0.9117260 0.7223300 Variables in the current scope: Attr Name Size Bytes Class ==== ==== ==== ===== ===== z 1x1 120 struct x 3x5 120 double Total is 16 elements using 240 bytes ===== Zapis w postaci tekstowej ===== x = rand(3,5); save 'zmienna2.dat' x -ascii z = load('zmienna2.dat'); whos z type 'zmienna2.dat' Variables in the current scope: Attr Name Size Bytes Class ==== ==== ==== ===== ===== z 3x5 120 double Total is 15 elements using 120 bytes 8.51829831e-01 3.14490508e-01 7.18888325e-01 1.94464344e-01 3.19602559e-01 4.86406622e-01 4.76122682e-02 8.42678715e-01 7.68031369e-01 1.11815726e-01 5.24032888e-01 5.59926339e-01 1.65799131e-01 9.59999895e-01 7.54648133e-01 ===== Odczyt obrazów ===== * ''%%imread('nazwa_pliku')%%'' odczyt pliku o podanej nazwie (JPEG, PNG, inne, …) * ''%%imfinfo('nazwa_pliku')%%'' informacje o opbrazie (np. szerokość i wysokość) * ''%%imwrite(X, 'nazwa_pliku')%%'' zapis macierzy ''%%X%%'' w postaci pliku graficznego (format okreslony rozszerzeniem) * ''%%imshow(X)%%'' wyświetla obraz zapisany w macierzy ''%%X%%'' * ''%%image(X)%%'' wyświetla zawartość macierzy w postaci obrazu (wartości mapowane sa na kolory pikseli) % Plik Lenna.png można pobrać ze strony https://en.wikipedia.org/wiki/Lenna % Odczyt pliku graficznego x = imread('Lenna.png'); whos x Variables in the current scope: Attr Name Size Bytes Class ==== ==== ==== ===== ===== x 512x512x3 786432 uint8 Total is 786432 elements using 786432 bytes % Wyswietlenie obrazu imshow(x) {{zajecia:pp2_2020_2:08_lab_files:08_lab_9_0.png| png}} % Informacje o pliku graficznym info = imfinfo('Lenna.png') info = scalar structure containing the fields: Filename = /home/marek/work/zajecia/2020.zimowy/pp2/github/Lenna.png FileModDate = 19-Jan-2021 09:39:34 FileSize = 473831 Format = PNG FormatVersion = Width = 512 Height = 512 BitDepth = 8 ColorType = truecolor DelayTime = 0 DisposalMethod = LoopCount = 0 ByteOrder = undefined Gamma = 0.45455 Chromaticities = Columns 1 through 6: 0.312700 0.329000 0.640000 0.330000 0.300000 0.600000 Columns 7 and 8: 0.150000 0.060000 Comment = Quality = 75 Compression = undefined Colormap = [](0x0) Orientation = 1 ResolutionUnit = undefined XResolution = 0 YResolution = 0 Software = Make = Model = DateTime = ImageDescription = Artist = Copyright = DigitalCamera = scalar structure containing the fields: GPSInfo = scalar structure containing the fields: % Wizualiacja elementów macierzy y = rand(100, 200) * 255; image(y) {{zajecia:pp2_2020_2:08_lab_files:08_lab_11_0.png| png}} image(x) {{zajecia:pp2_2020_2:08_lab_files:08_lab_12_0.png| png}} % adres URL zamiast nazwy pliku x = imread('https://wydzialy.umk.pl/_szablony/grafika/logo5.png'); whos x image(x) Variables in the current scope: Attr Name Size Bytes Class ==== ==== ==== ===== ===== x 392x866x3 1018416 uint8 Total is 1018416 elements using 1018416 bytes {{zajecia:pp2_2020_2:08_lab_files:08_lab_13_1.png| png}} % Odwrócenie kolorów (negatyw) y = 255 - x; image(y(:,:,1)); {{zajecia:pp2_2020_2:08_lab_files:08_lab_14_0.png| png}} % zapis macierzy w pliku graficznym imwrite(y(1:200,1:200,1), 'logo.bmp'); imfinfo('logo.bmp') ans = scalar structure containing the fields: Filename = /home/marek/work/zajecia/2020.zimowy/pp2/github/logo.bmp FileModDate = 21-Jan-2021 23:17:59 FileSize = 120054 Format = BMP FormatVersion = Width = 200 Height = 200 BitDepth = 8 ColorType = grayscale DelayTime = 0 DisposalMethod = LoopCount = 0 ByteOrder = undefined Gamma = 0 Chromaticities = [](1x0) Comment = Quality = 75 Compression = undefined Colormap = [](0x0) Orientation = 1 ResolutionUnit = Centimeter XResolution = 29.250 YResolution = 29.250 Software = Make = Model = DateTime = ImageDescription = Artist = Copyright = DigitalCamera = scalar structure containing the fields: GPSInfo = scalar structure containing the fields: % podgląd zapisanego pliku x = imread('logo.bmp'); image(x) {{.:08_lab_files:08_lab_16_0.png| png}} ===== Niskopoziomowe operacje na plikach ===== Podstawowe kroki postepowania: - Otworzenie pliku -> uzyskujemy deskryptor pliku - Operacje na pliku przy użyciu deskryptora: odczyt sekwencji danych, zapis, … - Zamknięcie pliku ===== Otwieranie i zamykanie plików ===== * ''%%fopen( 'nazwa', 'tryb' )%%'' otwiera plik o podanej nazwie. W przypadku niepowodzenia funkcja zwraca wartość ''%%-1%%''.\\ * Tryb otworzenia pliku: * ''%%'r'%%'' odczyt (domyślna wartość) * ''%%'w'%%'' zapis (poprzednia zawartość pliku zostaje skasowana) * ''%%'a'%%'' dodawanie zawartości na końcu instniejącego pliku * ''%%fclose(fid)%%'' zamyka plik wskazany deskryptorem ''%%fid%%'' * ''%%fclose('all')%%'' zamyka wszystkie otworzone pliki fid = fopen('plik.txt', 'r'); if fid == -1 disp('Problem z otworzeniem pliku') else disp('OK. Otworzyłem plik') fclose(fid) end Problem z otworzeniem pliku ===== Operacje odczytu z pliku ===== * ''%%fscanf(fid, 'format')%%'' wczytuje dane do macierzy zgodnie z zadanym formatem\\ * Format: * ''%%%f%%'' double, liczby rzeczywiste, * ''%%%d%%'' int, liczby całkowite, * ''%%%s%%'' napis, * ''%%%c%%'' znak. * ''%%textscan(fid, 'format')%%'' wczytuje dane do macierzy komórkowej zgodnie z podanym formatem * ''%%fgets(fid)%%'', ''%%fgetl(fid)%%'' wczytują linię tekstu z pliku * ''%%feof(fid)%%'' czy koniec pliku? ===== fscanf ===== * ''%%fscan(fid, 'format')%%'' wczytuje do macierzy wartości dopóki format jest zgodny lub do kóóńca pliku * jeśli wynikiem jest macierz liczb to ewentualne znaki zamieniane są na wartości kodu ASCII * ''%%%f%%'' i ''%%%d%%'' czyta kolejne liczby oddzielone białymi znakami (spacjami) * ''%%%c%%'' czyta dowolny znak (także spacje) type 'plik1.dat' fid = fopen('plik1.dat'); if fid ~= -1 a = fscanf(fid, '%f'); fclose(fid); end disp(a) whos a 42.300 Variables in the current scope: Attr Name Size Bytes Class ==== ==== ==== ===== ===== a 1x1 8 double Total is 1 element using 8 bytes fid = fopen('plik1.dat'); if fid ~= -1 a = fscanf(fid, '%f %c'); fclose(fid); end disp(a) disp(char(a(2))) % druga wartość to znak A whos a 42.300 65.000 A Variables in the current scope: Attr Name Size Bytes Class ==== ==== ==== ===== ===== a 2x1 16 double Total is 2 elements using 16 bytes fid = fopen('plik1.dat'); if fid ~= -1 a = fscanf(fid, '%c'); fclose(fid); end % wszystkie znaki wczytane do wektora kolumnowego disp(a) whos a 42.3 Anna 32.1 Jan 13.2 Janusz 5.4 Julia 3.3 Kacper Variables in the current scope: Attr Name Size Bytes Class ==== ==== ==== ===== ===== a 1x57 57 char Total is 57 elements using 57 bytes Okreslenie rozmiaru macierzy wyjściowej (liczby wczytanych wartości)\\ ''%%fscanf(fid, 'format', rozmiar)%%'' * rozmiar ''%%N%%'' wczyta okresloną liczbę wartości * rozmiar ''%%[N M]%%'' wczyta ''%%NxM%%'' wartości do macierzy * rozmiar ''%%[N Inf]%%'' wczyta wszystkie wartości do macierzy o ''%%N%%'' wierszach fid = fopen('plik1.dat'); if fid ~= -1 a=fscanf(fid, '%f %s\n', [5 Inf]); fclose(fid); end disp(a) % dane umieszczane w kolejnych kolumnach disp(char(a(:, 1))) whos a 42.30000 32.10000 74.00000 122.00000 105.00000 99.00000 65.00000 74.00000 97.00000 5.40000 97.00000 112.00000 110.00000 97.00000 110.00000 74.00000 3.30000 101.00000 110.00000 110.00000 117.00000 117.00000 75.00000 114.00000 97.00000 13.20000 115.00000 108.00000 97.00000 0.00000 * A n n a Variables in the current scope: Attr Name Size Bytes Class ==== ==== ==== ===== ===== a 5x6 240 double Total is 30 elements using 240 bytes **Ćwiczenie** wyznacz sumę wartośći zawartą w pierwszej kilumnie pliku ‘plik1.dat’ ===== fgetl() ===== * ''%%fgetl(fid)%%'' wczytuje linię z pliku (bez znaku nowej linii) * ''%%fgets(fid)%%'' wczytuje linię z pliku (ze znakiem nowej linii) fid = fopen('plik1.dat'); y = 0 if fid ~= -1 while feof(fid) == 0 linia = fgetl(fid); [x s] = strtok(linia); fprintf('x=%f s=%s\n', str2num(x), s); y = y + str2num(x); end fclose(fid); end disp(y) y = 0 x=42.300000 s= Anna x=32.100000 s= Jan x=13.200000 s= Janusz x=5.400000 s= Julia x=3.300000 s= Kacper 96.300 **Ćwiczenie** wyznacz sumę wartośći zawartą w pierwszej kilumnie pliku ‘plik1.dat’ czytając dane za pomocą ''%%fgetl%%'' ===== textscan ===== * ''%%textscan(fid, format)%%'' wczytuje dane do macierzy komórkowej * ''%%format%%'' analogicznie jak w ''%%printf%%'', np,: ''%%"%f %s"%%'' okresla liczbę double i następujący po spacji napis fid = fopen('plik1.dat'); if fid ~= -1 x = textscan(fid, '%f %s'); fclose(fid); end a = x{1} b = x{2} whos x a b a = 42.3000 32.1000 13.2000 5.4000 3.3000 b = { [1,1] = Anna [2,1] = Jan [3,1] = Janusz [4,1] = Julia [5,1] = Kacper } Variables in the current scope: Attr Name Size Bytes Class ==== ==== ==== ===== ===== x 1x2 64 cell a 5x1 40 double b 5x1 24 cell Total is 12 elements using 128 bytes fid = fopen('plik1.dat'); if fid ~= -1 x = textscan(fid, '%c'); fclose(fid); end whos x x Variables in the current scope: Attr Name Size Bytes Class ==== ==== ==== ===== ===== x 1x1 43 cell Total is 1 element using 43 bytes x = { [1,1] = { [1,1] = 4 [2,1] = 2 [3,1] = . [4,1] = 3 [5,1] = A [6,1] = n [7,1] = n [8,1] = a [9,1] = 3 [10,1] = 2 [11,1] = . [12,1] = 1 [13,1] = J [14,1] = a [15,1] = n [16,1] = 1 [17,1] = 3 [18,1] = . [19,1] = 2 [20,1] = J [21,1] = a [22,1] = n [23,1] = u [24,1] = s [25,1] = z [26,1] = 5 [27,1] = . [28,1] = 4 [29,1] = J [30,1] = u [31,1] = l [32,1] = i [33,1] = a [34,1] = 3 [35,1] = . [36,1] = 3 [37,1] = K [38,1] = a [39,1] = c [40,1] = p [41,1] = e [42,1] = r [43,1] = } } fid = fopen('plik1.dat'); if fid ~= -1 x = textscan(fid, '%s'); fclose(fid); end whos x x Variables in the current scope: Attr Name Size Bytes Class ==== ==== ==== ===== ===== x 1x1 42 cell Total is 1 element using 42 bytes x = { [1,1] = { [1,1] = 42.3 [2,1] = Anna [3,1] = 32.1 [4,1] = Jan [5,1] = 13.2 [6,1] = Janusz [7,1] = 5.4 [8,1] = Julia [9,1] = 3.3 [10,1] = Kacper } } **Ćwiczenie** wyznacz sumę wartości w pierwszej kolumnie pliku za pomocą ''%%textscan%%'' ===== Zapisywanie danych do pliku ===== * ''%%fprintf(fid, 'format', arg, ... )%%'' zapisuje dane w podanym formacie * argumentem może być wartość skalarna ale też i cała macierz fid = fopen('output.dat', 'w'); if fid ~= -1 fprintf(fid, 'Witaj Świecie\n'); for i=1:10 fprintf(fid, '%d do potęgi 2 wynosi %f\n', i, i^2); end fclose(fid); end type 'output.dat' Witaj Świecie 1 do potęgi 2 wynosi 1.000000 2 do potęgi 2 wynosi 4.000000 3 do potęgi 2 wynosi 9.000000 4 do potęgi 2 wynosi 16.000000 5 do potęgi 2 wynosi 25.000000 6 do potęgi 2 wynosi 36.000000 7 do potęgi 2 wynosi 49.000000 8 do potęgi 2 wynosi 64.000000 9 do potęgi 2 wynosi 81.000000 10 do potęgi 2 wynosi 100.000000 ===== Zapis macierzy ===== x = rand(5, 3) fid = fopen('macierz1.dat', 'w'); if fid ~= -1 fprintf(fid, '%f\n', x); fclose(fid); end x = 0.648652 0.058833 0.349327 0.768758 0.020663 0.141534 0.996369 0.347898 0.868106 0.377173 0.702610 0.584028 0.373202 0.469776 0.851421 type 'macierz1.dat' 0.648652 0.768758 0.996369 0.377173 0.373202 0.058833 0.020663 0.347898 0.702610 0.469776 0.349327 0.141534 0.868106 0.584028 0.851421 x = rand(5, 3) fid = fopen('macierz2.dat', 'w'); if fid ~= -1 fprintf(fid, '%f %f %f\n', x); fclose(fid); end x = 0.9933395 0.8791829 0.9703252 0.0179931 0.0372486 0.3797892 0.5577293 0.6500757 0.0090017 0.1238437 0.7979600 0.8138178 0.7468451 0.1667082 0.4569186 % elementy zapisane w kolejności kolumnowej type 'macierz2.dat' 0.993339 0.017993 0.557729 0.123844 0.746845 0.879183 0.037249 0.650076 0.797960 0.166708 0.970325 0.379789 0.009002 0.813818 0.456919 ===== Dodawanie zawartości do pliku ===== type 'output.dat' Witaj Świecie 1 do potęgi 2 wynosi 1.000000 2 do potęgi 2 wynosi 4.000000 3 do potęgi 2 wynosi 9.000000 4 do potęgi 2 wynosi 16.000000 5 do potęgi 2 wynosi 25.000000 6 do potęgi 2 wynosi 36.000000 7 do potęgi 2 wynosi 49.000000 8 do potęgi 2 wynosi 64.000000 9 do potęgi 2 wynosi 81.000000 10 do potęgi 2 wynosi 100.000000 fid = fopen('output.dat', 'a'); if fid ~= -1 fprintf(fid, 'Dopisek: %s\n', date); fclose(fid); end type 'output.dat' Witaj Świecie 1 do potęgi 2 wynosi 1.000000 2 do potęgi 2 wynosi 4.000000 3 do potęgi 2 wynosi 9.000000 4 do potęgi 2 wynosi 16.000000 5 do potęgi 2 wynosi 25.000000 6 do potęgi 2 wynosi 36.000000 7 do potęgi 2 wynosi 49.000000 8 do potęgi 2 wynosi 64.000000 9 do potęgi 2 wynosi 81.000000 10 do potęgi 2 wynosi 100.000000 Dopisek: 21-Jan-2021 ===== Zadanie 9. Szyfrowanie pliku ===== Stwórz plik o nazwie ''%%szyfr.m%%'' a w nim zdefiniuj funkcję o nazwe ''%%szyfr()%%'', która zaszyfruje zawartość pliku za pomocą algorytmu szyfrowania macierzowego. **Działanie szyfrowania macierzowego:** szyfrowany tekst umiszczamy w macierzy o liczbie kolumn K. Teskt umiszczany jest w kolejnych wierszach. Przykładowo, tekst ''%%tajna wiadomość%%'' umieszczony w macierzy o 5 kolumnach wypełni 3 wiersze (ewentualne brakujące elementy w ostatnim wierszu wypełniamy spacjami): tajna wiad omość Metoda polega na odczytaniu tekstu uzyskanego w kolumnach, czyli w tym przypadku wynikiem będzie: ''%%t oawmjionaśadć%%''. Ilość wierszy macierzy szyfrującej staje się kluczem pozwalającym odszyfrować wiadomość. Proces ten przebiega analogicznie, tzn. umieszczamy zaszyfrowany tekst w macierzy o 3 kolumnach (tyle wierszy miała macierz szyfrująca) i odczytujemy treść uzyskaną w kolumnach. t o awm jio naś adć Funkcja ''%%szyfr()%%'' przyjmuje 3 argumenty: nazwę pliku wejściowego, nazwę pliku wyjściowego oraz liczbę całkowitą okreslającą ilość kolumn macierzy szyfrującej. Funkcja zwraca liczbę całkowitą równą liczbie wierszy macierzy szyfrującej.\\ Przykładowo: x = szyfr('plik.txt', 'tajne.txt', 42); zaszyfruje zawartość pliku ''%%plik.txt%%'' za pomocą macierzy posiadającej 42 kolumny i zaszyfrowaną treść umieści w pliku ''%%tajne.txt%%''. Do zmiennej ''%%x%%'' zostanie podstawiowna liczba wierszy macierzy szyfrującej. Ta wartość stanowi klucz, który jest niezbędny do odszyfrowania wiadomości, tzn.: szyfr('tajne.txt', 'odszyfrowane.txt', x); umieści w pliku ''%%odszyfrowane.txt%%'' oryginalną, rozszyfrowaną treść pliku ''%%plik.txt%%''. Dwa pierwsze argumenty funkcji ''%%szyfr%%'' (nazwy plików) są obowiązkowe. W przypadku, gdy uzytkonik nie poda trzeciego argumentu wówczas liczba kolumn macierzy szyfrującej bedzie równa wartości $\sqrt{N}$ zaokrąglonej do liczby całkowitej, gdzie $N$ jest ilością wszystkich znaków w wiadomości do zaszyfrowania. W przypadku, gdy plik podany w pierszym argumencie nie istnieje, funkcja wyświetla stosowany komunikat błedu i skrypt kończy działanie. Uwaga: wystarczające jest aby prpgram obsługiwal poprawnie znaki z kodu ASCII.