下面是引用 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 桌布下载: