下面是引用 csr 於 2011-06-03 10:44 發表的 :
不好意思
大大的解釋
小弟似懂又非懂
也不知要怎麼來跟大大說出那裡不懂
不知大大可否用比較白話的方法幫小弟解釋
謝謝
實作的話會更清楚,我們就拿我從 DesktopNexus 下載的桌布來當作 argv[1] 的字串目標
請將 圖片
Chromatic_link_by_k3_studio.jpg (附在此文章最下面) 放置到工作目錄下
另外請下載一套免費的 文字/十六進位 編輯軟體 (建議下載 Portable 的):
RJ TextEd點選底下的 Editor 並將這張桌布 直接拖曳進去,就可以檢視 十六進位碼
這是我 修改後的原始碼,用這個比較貼近 軟體顯示的方法:
複製程式
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
int main(int argc, char *argv[])
{
long pos;
int fd;
int sector;
int totalread,totaldigit,totalchar;
int i,j;
char buffer[64];
argv[1]="Chromatic_link_by_k3_studio.jpg";
fd = open(argv[1],O_RDONLY | O_BINARY);
while ( 1 )
{
printf("輸入磁區 : ");
scanf("%d",& sector);
printf("\n");
if ( sector < 0 )
{
printf("結束隨機讀取資料 \n");
break;
}
pos = (long) sector * 64;
if ( lseek(fd,pos,SEEK_SET) == -1 )
{
printf("隨機讀取資料錯誤 \n");
break;
}
/* 讀取 64 位元組資料如果讀不到這麼多表示已讀到檔案末端 */
if ( ( totalread = read(fd,buffer,64) ) != 64 )
printf("EOF : end of file.... \n");
totalchar = totaldigit = totalread;
for ( i = 0; i < ceil((float)totalread / 16); i++ )
{
for ( j = 0; j < 16; j++ )
{
totaldigit--;
if ( totaldigit < 0 ) /* 無資料則列空白 */
printf(" ");
else /* 否則輸出 16 進位值 */
printf("%02X",buffer[i*16+j]<0 ? 255-(~buffer[i*16+j]) : buffer[i*16+j]);
if (j&1==1)
printf(" ");
}
printf(" "); /* 16 進位值和字元間的空白 */
for ( j = 0; j < 16; j++ )
{
totalchar--;
if ( totalchar < 0 )
printf(" "); /* 輸出完成後用空白取代 */
else
if ( isprint(buffer[i*16+j]) )
printf("%c",buffer[i*16+j]);/*輸出字元*/
else /* 非字元則用 . 取代 */
printf(".");
}
printf("\n");
}
printf("\n");
}
close(fd);
return 0;
}
(請用平面式 左到右 來想像檔案中的位元組)
首先,磁區開始 因為 lseek(fd,pos,SEEK_SET) 而被設定 位移量 將從 SEEK_SET 當作基準點
磁區為什麼要乘以 64? 因為他設定 buffer 一次要讀 64 個位元組,當然也可以設定不要乘以 64
那麼你輸入磁區的時候就要打 64, 128, 192 豈不是很麻煩
讀了 檔案中某一塊 64 的位元組後,接下來程式就是要顯示 這64個位元組資料 是什麼東西
他很想要模擬 UltraEdit 那樣一行顯示 16 個 16進位碼
請注意底下的像是 FFD8 其實是
2 個位元組 組成的,原本是要顯示 FF D8 但我想把他合在一起
十六進位的 FF 就是 十進位的 255 剛好是 2 的 8 次方-1 ,這就是 1 位元組有8個位元裝得下最大的數字 (unsigned) (最小是 0)
至於接下來除以 16 就是不想要一行 顯示 64 個,這樣會超出視窗範圍
因此他將 64 切成 4 塊 (顯示會顯示 4 行) 來顯示,64 / 4 = 16 ,這就是 16 的由來
至於
i*16+j 則是在 64 位元組內 的 位移量
在迴圈內
i*16+j 跑起來將會從 0~63 剛好一次讀一個位元組
至於達到 EOF 時候,buffer[
i*16+j] 內是沒有讀到東西的
則將會顯示空白
你可以把
RJ TextEd 與 程式的結果來對照,請輸入
磁區 0 來比對比較輕鬆
將發現 16進位碼是 一模一樣
很有趣的,
磁區2 裡面會看到 Adobe Photoshop CS2 甚至還有時間
他這張桌布是用哪個軟體編輯的還有儲存時間 都很明顯
Chromatic_link_by_k3_studio.jpg 桌布下載: