MATLAB fread函式分析
今天起開始總結下MATLAB的檔案操作函式。MATLAB的確用起來很方便,前提是你瞭解它的函式~
MATLAB的幫助文件看的那叫一個似懂非懂啊,特此總結。對我而言, fread的主要呼叫形式是這樣的:
data = fread(fid, N, 'str')
fid不用說,自然是檔案控制代碼(如fid=fopen('abc.txt' ,'r')),N是讀入的元素個數,'str'是格式。在以前不會用的時候,格式都是直接省略的,這個時候函式就一個位元組一個位元組地從檔案中讀入資料,再在MATLAB中轉化為double形式。
如果檔案時二進位制檔案,這樣讀當然沒問題,如果想要讀入的是文字,那就不行了。文字也是一個位元組一個位元組地讀,但是最後應該轉化為char型:
>> frewind(f);
>> a=fread(f,1,'char=>char')
a =
B
>> frewind(f);
>> a=fread(f,1,'uchar=>uchar')
a =
66
>> class(a)
ans =
uint8
>> frewind(f); >> a=fread(f,1,'uint8=>char') a = B >> frewind(f); >> a=fread(f,1,'uchar=>char') a = B>> frewind(f); >> a=fread(f,1,'int8=>char') a = B
上面是一個BMP檔案的例子,讀入的是檔案第第一個位元組,BMP檔案以“BM”開頭,第一個自己自然是B。int8、uint8、char、uchar是幾種一個位元組的資料型別。在例子中,a=>b表示以a的型別讀入,再轉化為b型別。a的作用是控制每次讀入的位元組數,然後轉化為相應的型別,形成一定的數值,b的作用是在a的基礎上進行轉化。這裡都是一個位元組,讀入以後,最後如果是char型,就都變成了字母B,如果是uchar型,就變成uint8。
以上是位元組數相同的例子,a=>b,a似乎沒多大用,但是,當位元組數不同時,就大有用場了:
>> frewind(f); >> a=fread(f,1,'uint16=>uint8') a = 255 % 在這裡,uint16是兩個位元組的,所以一次性讀入2個位元組,先以uint16的形式讀入,整數的排列規則是很簡單的,假設低位元組為a,高位元組為b,那就等於b*256+a,得到的數肯定超過256,最後又要轉化為uint8,因此只能截斷了,uint8一個位元組,最大能表示的數就是255,因此返回255.
>> frewind(f);
>> a=fread(f,1,'uint16=>float')
a =
19778
% 這裡,說明以uint16讀入的數,得到為19778,然後再轉為單精度的float型,還是19778,當然,型別已經換掉了
>> frewind(f);
>> a=fread(f,1,'*uint32')
a =
37637442
% *uint32相當於uint32=>uint32,以4個位元組的形式讀入,成為一個整數。
>> frewind(f);
>> a=fread(f,1,'uint32=>float')
a =
37637440
% 以四個位元組的形式讀入,先變成整型,再變成float型,末尾的2丟掉了,是精度問題?
>> class(a)
ans =
single
>> frewind(f);
>> a=fread(f,1,'uint32=>double')
a =
37637442
% 轉化為double,精度就夠了
>> frewind(f);
>> a=fread(f,1,'float=>double')
a =
1.3981e-037
% 最精彩的來了,儘管float和uint32都是4個位元組,但是這裡得到的數卻不與上面相等。前面說了,a=>b,系統以a的格式,讀入相應的位元組數,轉化為a型別的一個數值,再將a轉為b型別,這裡讀入的時候,以float的規則來讀,再將float轉為double,無非是提高精度而已。
>> frewind(f);
>> a=fread(f,1,'float=>uint32')
a =
0
% 讀到的是1.3981e-037,轉化為整數,當然是0了
此外,我還嘗試過以下格式:
>> a=fread(f,1,'3*int8=>char')
a =
B
N*a=>b的形式,一般用在有skip(跳過)的地方,這裡沒有在後面的引數中指定跳過,所以預設的跳過為零,得到的結果還是字母B。跳過形式往往用在按bit讀的時候,
>> a=fread(f,3,'*uint8')
a =
66
77
62
>> frewind(f);
>> a=fread(f,4,'1*int8=>int8',1)
a =
66
62
2
0
% 注意,前面讀入的時候按int8讀,所以跳過的時候,跳的是1個int8的長度,因此跳過了77,結果為66,,62
>> frewind(f);
>> a=fread(f,2,'1*bit8=>int8',8)
a =
66
62
% 前面是bit8,凡是bitN的型別的,後面跳過時都指的是跳過幾個bit
>> frewind(f); >> a=fread(f,2,'1*bit16=>int8',8)
a =
127 2
%前面讀入是按兩個位元組讀(bit16),因此第一次讀進來的是66和77,後來要轉為int型,int表示的範圍-128~127,因此就變成127了。然後跳過了62,下一個數字是2,在下一個數字是0,因此加在一起就是0了。
另外,最全的呼叫形式是
[data, n] = fread(fid, N, 'a=>b', nn, 'l/n/b/...')
最後一個引數的作用是指定大端小端,windows這種用intel的是小端,低地址放低位元組,所以讀進66和77,66在低地址,他是低位元組,77是高地址,是高位元組,結果為66+77*256,UINX之類的一般是大端。網路通訊一般是大端
'b' :大端
'l' :小端
'n' :原來是大端現在就是大端,原來小端現在就是小端!
返回的n是指實際讀進了幾個單元。把n和N一比較,相等就說明確實讀進了所需要的N個數據。
測試用的檔案: