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)

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)

png

image(x)

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

png

% Odwrócenie kolorów (negatyw)
y = 255 - x;
image(y(:,:,1));

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)

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 zaokrąglonej do liczby całkowitej, gdzie 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.