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, …
  • 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
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
  • 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

Podstawowe kroki postepowania:

  1. Otworzenie pliku → uzyskujemy deskryptor pliku
  2. Operacje na pliku przy użyciu deskryptora: odczyt sekwencji danych, zapis, …
  3. Zamknięcie pliku
  • 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
  • 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?
  • 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(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(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

  • 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
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
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

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.