MATLAB ADATOK BEOLVASÁSA/KIÍRÁSA FÁJLBA Parancsok: load save fopen fclose fseek feof fgetl fgets fscanf sscanf textscan fprintf sprintf
dlmread dlmwrite fileread fread
- Load workspace variables from disk, load filename - Save workspace variables to disk, save filename variables -ascii -append - Open file, or obtain information about open files, fileID = fopen(filename) - Close one or all open files, fclose(fileID) - Move to specified position in file, fseek(fileID, offset, origin) - Test for end-of-file, feof(fileID) - Read line from file, removing newline characters, fgetl(fileID) - Read line from file, keeping newline characters, fgets(fileID) - Read formatted data from a text file, converts data into array fscanf(fileID, format) - Read formatted data from string, sscanf(str, format) - Read formatted data from text file or string, returns a cell array, textscan(fid, 'format') - Write data to text file, fprintf(fileID, format, A, ...) - Format data into string, sprintf(format, A, ...)
- Read ASCII-delimited file of numeric data into matrix, M = dlmread(filename, delimiter) - Write matrix to ASCII-delimited file, dlmwrite(filename, M, 'D') - Read contents of file into string, text = fileread(filename) - Read data from binary file
FORMÁZOTT SZÖVEGES ÁLLOMÁNYOK ÍRÁSA, OLVASÁSA (FPRINTF, SPRINTF, SSCANF, TEXTSCAN) Az fprintf paranccsal a képernyőre vagy fájlba írhatunk formázott szövegeket, az sprintf használatval pedig egy stringbe. Ugyanazokat a formátumjelölőket alkalmazhatjuk, mint korábban is. %d – egész szám, %s – szöveg, %f – valós szám (lebegőpontos), %c – karakter, %u – nem előjeles egész %e – normál alak pl. 3.14e+00, %E – 3.14E+00 %g – kompakt forma f vagy e, amelyik rövidebb, fölös 0-k nélkül A típust jelző betű előtt szerepelhet még pl. + jel, akkor előjelesen írja ki a számot, mező szélesség, tizedesjegyek száma, 0, akkor 0-kal tölti fel elől az üres helyeket a mező szélességéig. 1
Pl. sprintf('%0+6.2f',pi) → +03.14 A mező szélessége 6 (tizedespontot is beleértve!), a tizedesjegyek száma 2, kiírja az előjelet és 0-kat, hogy meglegyen a 6 széles mező (0 nélkül szóközökkel töltené fel), így írja ki a pi értékét. Ha az eredmény hosszabb, mint a mező szélessége, akkor nem veszi figyelembe a megadott mező szélességet. Pl. sprintf('%2.5f',1/eps) → 4503599627370496.00000 sprintf('%2.5g',1/eps) → 4.5036e+015 fid=fopen('ciklus.txt','w'); for i=1:3 fprintf(fid,'Ciklus változó: %d\n',i); end fclose(fid);
Eredmény: ciklus.txt Ciklus változó: 1 Ciklus változó: 2 Ciklus változó: 3
Az sscanf paranccsal fromázott szövegeket olvashatunk be stringből egy mátrixba [a, count] = sscanf (s, format, size) –’count’ a beolvasott elemek száma és ’size’ opcionális pl. : d='23 bg 45 mn' a=sscanf(d, '%f') → 23 (az első nem szám karakternél leáll) a=sscanf(d, '%f %s') → 23 98 103 45 109 110 (98=b ASCII kódja stb.) a=sscanf(d, '%f %*s') → 23 45 (átugorja a szöveget a szám után) A textscan paranccsal szintén formázott szövegeket olvashatunk be, de itt nem mátrixba, hanem cellatömbbe, így eltérő típusú adatokat is tárolhatunk. Néhány formátum megadási lehetőség: %d – egész szám, %s – szöveg, %f – valós szám, %c – karakter, %u – nem előjeles egész %*s vagy %*f átugorja, nem olvassa be, a szöveg vagy valós szám típusokat betű szerinti megadás – amit leírtunk azt kihagyja pl. ’Level1’ tartalmú szövegből a 'Level%d' csak az 1-et fogja beolvasni Pl. Egy stringből beolvasunk két tizedesjegyű számokat, úgy, hogy a második jegyet elhagyjuk! str='0.41 8.24 3.57 6.24 9.17'% szöveges adat c=textscan(str, '%3.1f %*1d'); % %3.1f forma 1 tizedesre olvas számot, %*1d pedig % kihagyja a következő 1 számjegyű egész számot
2
c{1}=[0.4;8.2;3.5;6.2;9.2] Néhány textscan parancsnál használható opció: 'delimiter', ',' 'MultipleDelimsAsOne', 1) 'treatAsEmpty', {'NA', 'na'} 'commentStyle', '//'
meg lehet adni az elválasztó karaktert meg lehet adni, hogy összevonja a többszörös elválasztókat milyen karaktert tekintsen üres (NaN) értéknek mi a komment, amit figyelmen kívül hagy
EGYSZERŰ ADATBEOLVASÁS/KIÍRÁS (LOAD, SAVE) A legegyszerűbb adatbeolvasás/kiírás a load illetve save paranccsal történhet. Szöveges fájl beolvasásánál azonos típusú adatok és azonos sorhosszak szükségesek. Az eredmény egy mátrixba kerül, amiben csak azonos típusú elemek lehetnek. Save-vel elmenthetjük a munkakörnyezet összes vagy néhány változóját *.mat kiterjesztésű MATLAB bináris fájlba, amiből utána load-dal ezek betölthetőek, de ez más program számár a nem igazán értelmezhető formátum. Ha szöveges állományba kívánjuk menteni egy mátrix tartalmát, akkor a save filename variables –ascii paranccsal tehetjük meg. Ha egy létező fájlhoz akarunk hozzáírni valamit, akkor a save filename variables ascii –append parancsot használhatjuk. PÉLDA (SAVE, LOAD HASZNÁLATA MÁTRIX SZÖVEGES ÁLLOMÁNYBA MENTÉSÉHEZ, BEOLVASÁSÁHOZ) clc; clear all; % Vegyünk fel egy 2x3 véletlen mátrixot A1=rand(2,3) % A1 = 0.5688 0.0119 0.1622 % 0.4694 0.3371 0.7943 % Mentsük el a testfile.dat szöveges állományba a mátrix tartalmát! save testfile.dat A1 -ascii % Nézzük meg a fájl tartalmát type testfile.dat 5.6882366e-001 1.1902070e-002 1.6218231e-001 4.6939064e-001 3.3712264e-001 7.9428454e-001 % Vegyünk fel egy második 3x3-as véletlen mátrixot A2=rand(3,3) % A2 = 0.3112 0.6020 0.6892 % 0.5285 0.2630 0.7482 % 0.1656 0.6541 0.4505 % Fűzzük hozzá az előző állományhoz save testfile.dat A2 -ascii -append % Olvassuk be a testfile tartalmát! load testfile.dat % Nézzük meg mit tartalmaz a testfile mátrix4
3
testfile % testfile = % 0.5688 % 0.4694 % 0.3112 % 0.5285 % 0.1656
0.0119 0.3371 0.6020 0.2630 0.6541
0.1622 0.7943 0.6892 0.7482 0.4505
% Fűzzünk még hozzá tetszőleges számú sort/oszlopot! r=input('Hány sort fűzzek még hozzá? '); o=input('Hány oszlopot fűzzek hozzá? '); A3=rand(r,o) save testfile.dat A3 -ascii –append % Nézzük meg most a type testfile.dat % 5.6882366e-001 % 4.6939064e-001 % 3.1121504e-001 % 5.2853314e-001 % 1.6564873e-001 % 8.0006848e-001 % 4.3141383e-001
fájl tartalmát, ha 2 sort és 4 oszlopot adtunk meg 1.1902070e-002 3.3712264e-001 6.0198194e-001 2.6297128e-001 6.5407910e-001 9.1064759e-001 1.8184703e-001
1.6218231e-001 7.9428454e-001 6.8921450e-001 7.4815159e-001 4.5054160e-001 2.6380292e-001 1.4553898e-001
1.3606856e-001 8.6929221e-001
% A fenti állományt már nem tudju a load paranccsal betölteni, mivel nem % egyenlő hosszúal a sorok! Ehhez más parancsra lesz szükség!
MÁTRIX FORMÁTUMTÓL ELTÉRŐ ADATOK BEOLVASÁSA Ha a beolvasni kívánt szöveges állományunk nem egy mátrix formátumában tartalmaznak adatokat (azonos típus, azonos sorhosszak), akkor az ún. alacsony szintű adatbeolvasási/írási műveleteket kell használni. Ezek általánosan a következőképp néznek ki: fájl megnyitása (fopen) beolvasás, írás, hozzáfűzés a fájlhoz fájl bezárása (fclose) Az fopen használata során megadhatjuk, hogyan kívánjuk megnyitni a fájlt, ’r’-csak olvasásra (alapértelmezett, ha nem adunk meg semmit), ’w’-írásra, ’a’-hozzáfűzéshez: fileID = fopen(filename,’w’) – fájl megnyitásra írásra A fájlokat bezárhatjuk egyenként: fclose(fileID), vagy egyszerre az összeset: fclose(’all’). Az fopen, fclose használata mellett szükségünk lehet még az feof parancsra a soronkénti fájl beolvasásnál, ami megmondja, hogy már a fájl végére értünk-e, illetve az fseek parancsra, amivel tetszőleges helyre ugorhatunk a fájlban, például a fájl elejére, ha újra be akarunk belőle olvasni valamit. A beolvasás, íráshoz a következő parancsokat fogjuk most megnézni: beolvasás: fgetl, fgets, fscanf, textscan, sscanf írás: fprintf, sprintf 4
Az fgetl és fgets parancsokkal soronként lehet beolvasni egy fájl tartalmát, az fgetl levágja belőle a sorvége karaktert, míg az fgets megtartja. A beolvasás eredménye egy string változóba kerül. Az fscanf parancs az egész fájt beolvassa egy mátrixba, egy adott formátum szerint. Formátum megadására szolgáló karakterek pl. %d – egész típus, %s – string, %f – valós, %c – karakter, %u – nem előjeles egész. A textscan parancs az egész szöveget szintén formátum szerint olvassa be, viszont nem mátrixba, hanem cella tömbbe (cell array), így különböző típusú adatokat is be tudunk egyszerre olvasni (egy mátrixban csak azonos típusú elemek lehetnek). Olvassuk be a következő állományt, amiben betűk és számok is vannak: szambetu.dat 5.3 a 2.2 b 3.3 a 4.4 a 1.1 b SORONKÉNT BEOLVASÁS (FGETL, FGETS) Az fgetl és fgets parancsokkal soronként lehet beolvasni egy fájl tartalmát, az fgetl levágja belőle a sorvége karaktert (\n vagy \r\n)1, míg az fgets megtartja. A beolvasás eredménye egy string változóba kerül. Az egész fájl tartalom beolvasásához egy feltételes ciklusra van szükség (while), hogy addig olvasson, amíg el nem érünk a fájl vége jelhez (feof). PÉLDA FGETL HASZNÁLATÁRA SZÁMOK/BETŰK SZÉTVÁLASZTÁSÁRA clear all;clc; % Fájl megnyitás (az alapértelmezett olvasásra) fid=fopen('szambetu.dat'); szamok=[];betuk=[]; % számok és betűk tömbök létrehozása % Sorok beolvasása, számok, betűk szétválasztása, kiíratása (szamok 2 tizedesre) while feof(fid)==0 % ciklus, amíg a fájl végére érünk line=fgetl(fid); % egy sor beolvasása % szöveg szétválasztása az alapértelmezett szóköznél2 [szam betu]=strtok(line); % Írassuk ki a két tizedesre a számokat, majd a betűket a képernyőre! % A szöveg első felét számmá kell konvertálni (string típusból) fprintf('%.2f %s\n', str2num(szam), betu) szamok=[szamok;str2num(szam)]; % szam hozzáfűzése a szamok tömbhöz betuk=[betuk;betu]; % betű hozzáfűzése a betuk tömbhöz end % Fájl bezárása 1
A sor vége jel Windows esetében: \r\n, Mac (OS 9-) esetében \r, Unix/Linux esetében: \n.
Az strtok a stringet kettéválasztja vagy az alapértelmezett szóköznél, vagy egy megadott elválasztó (delimiter) karakternél pl. , ; 2
5
fclose(fid); % Írassuk ki a számok összegét a képernyőre! szumma=sum(szamok); fprintf('A számok összege: %.2f\n',szumma)
Az eredmény: 5.30 a 2.20 b 3.30 a 4.40 a 1.10 b A számok összege: 16.30 BEOLVASÁS FSCANF HASZNÁLATÁVAL Az fscanf paranccsal egyszerre az egész fájlt be tudjuk olvasni egy megadott formátum szerint. Az eredmény egy mátrixba kerül. Ezzel a paranccsal különböző hosszúságú sorokat nem tudunk beolvasni. A beolvasás oszloponként történik, megadjuk a formátumot, amiben az adatok le vannak tárolva pl. először egy szám, aztán egy betű stb. Ekkor először az első oszlop kerül beolvasásra, amiben a számok vannak, ez kerül az első sorba, utána a második oszlop a betűkkel, ez kerül a második sorba. Ez utóbbiak viszont ASCII kódokkal kerülnek tárolásra, mivel egy mátrixon belül csak azonos típusú elemek lehetnek. Nézzük meg az előző példát fscanf-fel! PÉLDA FSCANF HASZNÁLATÁRA SZÁMOK/BETŰK SZÉTVÁLASZTÁSÁRA clear all;clc; % Fájl megnyitás (az alapértelmezett olvasásra) fid=fopen('szambetu.dat'); mat=fscanf(fid,'%f %s',[2 inf]); % Az fscanf-nél fontos a szóköz is a két formátum között. Ha %f%s-t % adnánk meg, akkor a szám és betű közti szóközt olvasná be a betű helyett. % [2 inf] a dimenzió ahol inf szerepel, ha nem tudjuk milyen hosszú a fájl szamok=mat(1,:) betuk=char(mat(2,:)) % át kell alakítani az ASCII kódokat karakterekké fclose(fid);
Eredmény: mat = 5.3000 2.2000 3.3000 4.4000 1.1000 97.0000 98.0000 97.0000 97.0000 98.0000 % ASCII kódjai a betűknek szamok =
5.3000
2.2000
3.3000
4.4000
betuk = abaab 6
1.1000
A mat tömbben a betűk helyett azok ASCII kódját jeleníti meg (egy mátrixban nem lehetnek különböző elemek. Az fscanf-hez hasonlóan használható az sscanf, csak ez nem fájlból olvas be adott formátum szerint, hanem stringből!
BEOLVASÁS TEXTSCAN HASZNÁLATÁVAL C = textscan(fid, 'format', param, value, ...) A textscan paranccsal is az egész fájlt be lehet egyszerre olvasni egy adott formátum szerint, különbség, hogy itt a beolvasott adatok cella tömbben kerülnek tárolásra, nem mátrixban, így különböző típusú adatokat is le lehet egyszerre tárolni. Vigyázni kell, hogy a cella elemire kapcsos zárójellel {} lehet hivatkozni, nem úgy, mint a mátrix elemeire () sima zárójellel! A textscan nem csak fájlból, hanem string típusú változóból is képes adatot beolvasni a megadott formátum szerint! Nézzük meg az előző példát textscan-nel! PÉLDA TEXTSCAN HASZNÁLATÁRA SZÁMOK/BETŰK SZÉTVÁLASZTÁSÁRA clear all; clc; % Fájl megnyitása, beolvasás, lezárás fid=fopen('szambetu.dat'); adatok=textscan(fid, '%f %s'); fclose(fid); % Eredmények szétválasztása a cella tömbből szamok=adatok{1} betuk=adatok{2} % Eredmények kiíratása fprintf-fel, 1 tizedesre a számok l=length(adatok{1}); for i=1:l fprintf('%.1f %c\n', adatok{1}(i),char(adatok{2}(i))) end % Átlag kiszámítása fprintf('Az átlag=%.2f.\n',mean(adatok{1}))
Eredmények: szamok = 5.3000 2.2000 3.3000 4.4000 1.1000 betuk = a b a a 7
b 5.3 a 2.2 b 3.3 a 4.4 a 1.1 b Az átlag=3.26. PÉLDA XY KOORDINÁTÁK BEOLVASÁSÁRA ÉS PLOTTOLÁSÁRA, FGETL, FSCANF ÉS TEXTSCAN HASZNÁLATÁVAL (A HÁROM MÓDSZER ÖSSZEHASONLÍTÁSA)
A beolvasandó x és y koordinátákat tartalmazó mintapélda a következő: xypoints.dat x2.3y4.56 x7.7y11.11 x12.5y5.5 clear all;clc; fid=fopen('xypoints.dat'); type xypoints.dat % x,y koordináták beolvasása %% 1. megoldás - fgetl x=[];y=[]; % x,y tömb létrehozása while ~feof(fid) line=fgetl(fid); % 1 sor beolvasása line=line(2:end); % első karaktert elhagyjuk (x) [xstr rest]=strtok(line,'y'); % maradékot szétválasztju az 'y'-nál x=[x str2num(xstr)]; % elejét hozzáfűzzük az x tömbhöz számmá konvertálva ystr=rest(2:end); % a maradék elejéről is lehagyunk egy karaktert (y) y=[y str2num(ystr)]; % hozzáfűzzük y tömbhöz számként end % x = 2.3000 7.7000 12.5000 % y = 4.5600 11.1100 5.5000 %% 2. megoldás - fscanf fseek(fid, 0, 'bof'); % ugrás a fájl elejére a következő beolvasáshoz mat=fscanf(fid,'x%fy%f\n',[2 inf]) % Ha dimenziót nem adunk meg, akkor egy vektorban tárol el minden adatot. % Kell a sorvége karakter is, különben azt olvassa be következő karakternek. % Ha számot keresne, akkor átugorná a szóközt, sorvége karaktert. % mat = % 2.3000 % 4.5600
7.7000 11.1100
12.5000 5.5000
x=mat(1,:); y=mat(2,:); %% 3. megoldás - textscan fseek(fid, 0, 'bof'); %ugrás ismét a fájl elejére xydat=textscan(fid,'x%fy%f') % itt nem kell sorvége karakter, mivel itt a formátum az oszlopok % szerkezetét definiálja a fájlban, nem azt, hogy mit kell a sorból % beolvasni
8
% xydat = [3x1 double] x=xydat{1}; y=xydat{2};
[3x1 double]
closeresult=fclose(fid); % Plottolás plot(x,y,'b*')
PÉLDA INTERFEROMÉTERES ADATOK BEOLVASÁSÁRA
HEADER File type : rtl … Run Target Data: 1 1 7.403 1 2 -994.335 2 2 -1008.836 2 1 196.273 3 1 81.117 … ENVIRONMENT:: Air temp : 22.445311 22.460936 0 … EOF A fájl elején 26 sornyi fejléc, utána a lényeges információ: számok 3 oszlopban, tetszőleges sorban, majd egyéb szöveges információk. A számokat az alábbi parncsokkal lehet egy mátrixba menteni: a=textread('teszt03.rtl', '%s', 'headerlines', 26, 'whitespace', '') b=sscanf(a{1},'%f',[3,inf])
A textread-del beolvassuk a szöveget egy szöveg cellába, úgy, hogy átugorjuk a 26 sornyi fejlécet. Hogy ne szabdalja szét a szóközöknél a ’szóköz’ karaktert üres karakterre '' állítjuk. Utána beolvassuk az sscanf paranccsal a számokat egy tömbbe, amit 3 oszlopban tárolunk. Az sscanf parancs leáll automatikusan az első olyan karakternél, ami nem felel meg a szám követelménynek, a sorok pontos számát nem kell megadni.
9