這個(gè)一般是打不開的,打開就等于是盜用人家的代碼。
創(chuàng)新互聯(lián)從2013年創(chuàng)立,先為正陽(yáng)等服務(wù)建站,正陽(yáng)等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為正陽(yáng)企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
lib文件
意義:
lib有靜態(tài)lib和動(dòng)態(tài)lib之分。
使用:
lib文件通過編譯才可以使用,編譯分靜態(tài)與動(dòng)態(tài)之分。
靜態(tài):
靜態(tài)lib將導(dǎo)出聲明和實(shí)現(xiàn)都放在lib中。編譯后所有代碼都嵌入到宿主程序
動(dòng)態(tài):
動(dòng)態(tài)lib相當(dāng)于一個(gè)h文件,是對(duì)實(shí)現(xiàn)部分(.dll文件)的導(dǎo)出部分的聲明。編譯后只是將導(dǎo)出聲明部分編譯到宿主程序中,運(yùn)行時(shí)候需要相應(yīng)的dll文件支持
詳細(xì)說(shuō)明:
lib文件是不對(duì)外公開的,不能查看一個(gè)編譯過后的文件
有幾個(gè)選擇:
1。如果你查看有同名的dll文件,可以通過vc自帶的depends查看dll接口
2。通過msdn看你使用的該lib包含的函數(shù)名,來(lái)查找其對(duì)應(yīng)的頭文件,頭文件里面有整個(gè)lib的函數(shù)聲明(可能不全)
3。查看vc或者其他工具安裝目錄下的src目錄,查看函數(shù)的代碼
lib文件是二進(jìn)制文件,所以要查看它的內(nèi)容,只能反匯編。
用編程語(yǔ)言,打開lib文件的辦法有三個(gè):
1、在object/library modules使用全路徑名;
2、把*.lib放在VC的Lib目錄中
3、修改project setting的Link-Input中的Addtional library path,加入你的目錄。
LIB文件是庫(kù)文件(與DLL文件相類似),供其它程序調(diào)用的,直接打不開。
內(nèi)容
一個(gè)lib文件是obj文件的集合。當(dāng)然,其中還夾雜著其他一些輔助信息,目的是為了讓編譯器能夠準(zhǔn)確找到對(duì)應(yīng)的obj文件。我們可以通過tlib.exe(在tc2.0下的根目錄)來(lái)對(duì)lib文件進(jìn)行操作,你可以把自己生成的obj文件通過tlib命令加入到一個(gè)lib文件中,也可以把lib文件內(nèi)的obj文件進(jìn)行刪除操作,還可以把內(nèi)部的obj文件給提取出來(lái)。明白了lib文件的大致結(jié)構(gòu)以及對(duì)它的具體操作,在學(xué)習(xí)C語(yǔ)言的過程中,就會(huì)又多了一個(gè)切入點(diǎn)對(duì)C語(yǔ)言具體實(shí)現(xiàn)進(jìn)行研究。
使用步驟
在command下,把當(dāng)前目錄設(shè)置為tlib.exe所在目錄,然后輸入tlib命令回車,此時(shí)顯示的內(nèi)容就是對(duì)tlib命令的詳細(xì)解釋,語(yǔ)法如下:
Syntax: TLIB libname [/C] [/E] commands, listfile
libname library file pathname
commands sequence of operations to be performed (optional)
listfile file name for listing file (optional)
A command is of the form: symbolmodulename, where symbol is:
+ add modulename to the library
- remove modulename from the library
* extract modulename without removing it
-+ or +- replace modulename in library
-* or *- extract modulename and remove it
/C case-sensitive library
/E create extended dictionary
具體解釋:
tlib libname [/C] [/E] commands, listfile
/C:大小寫敏感標(biāo)志。該選項(xiàng)不常用,此參數(shù)為可選項(xiàng)。
/E:建立擴(kuò)展字典。建立擴(kuò)展字典可以加速大的庫(kù)文件的連接過程,此參數(shù)同樣為可選項(xiàng)。
操作命令(可選項(xiàng)):
+ obj文件名 把指定obj文件添加到lib文件中
- obj文件名 把指定obj文件從lib文件中刪除
* obj文件名 導(dǎo)出指定的obj文件(導(dǎo)出后對(duì)應(yīng)的obj文件在lib文件內(nèi)仍然存在)
-+ obj文件名 替換指定的obj文件(前提是在lib文件中存在與指定obj文件同名的obj)
-* obj文件名 導(dǎo)出指定的obj文件(導(dǎo)出后把對(duì)應(yīng)的obj文件從lib文件內(nèi)刪除)
lib文件中obj文件列表(可選項(xiàng))
此參數(shù)說(shuō)明了命令運(yùn)行后,生成的對(duì)應(yīng)lib文件的列表文件名。它記錄了當(dāng)前l(fā)ib文件內(nèi)obj文件列表
與dll區(qū)別編輯
(1)lib是編譯時(shí)需要的,dll是運(yùn)行時(shí)需要的。
如果要完成源代碼的編譯,有l(wèi)ib就夠了。
如果也使動(dòng)態(tài)連接的程序運(yùn)行起來(lái),有dll就夠了。
在開發(fā)和調(diào)試階段,當(dāng)然最好都有。
(2)一般的動(dòng)態(tài)庫(kù)程序有l(wèi)ib文件和dll文件。lib文件是必須在編譯期就連接到應(yīng)用程序中的,而dll文件是運(yùn)行期才會(huì)被調(diào)用的。如果有dll文件,那么對(duì)應(yīng)的lib文件一般是一些索引信息,具體的實(shí)現(xiàn)在dll文件中。如果只有l(wèi)ib文件,那么這個(gè)lib文件是靜態(tài)編譯出來(lái)的,索引和實(shí)現(xiàn)都在其中。靜態(tài)編譯的lib文件有好處:給用戶安裝時(shí)就不需要再掛動(dòng)態(tài)庫(kù)了。但也有缺點(diǎn),就是導(dǎo)致應(yīng)用程序比較大,而且失去了動(dòng)態(tài)庫(kù)的靈活性,在版本升級(jí)時(shí),同時(shí)要發(fā)布新的應(yīng)用程序才行。
(3)在動(dòng)態(tài)庫(kù)的情況下,有兩個(gè)文件,一個(gè)是引入庫(kù)(.LIB)文件,一個(gè)是DLL文件,引入庫(kù)文件包含被DLL導(dǎo)出的函數(shù)的名稱和位置,DLL包含實(shí)際的函數(shù)和數(shù)據(jù),應(yīng)用程序使用LIB文件鏈接到所需要使用的DLL文件,庫(kù)中的函數(shù)和數(shù)據(jù)并不復(fù)制到可執(zhí)行文件中,因此在應(yīng)用程序的可執(zhí)行文件中,存放的不是被調(diào)用的函數(shù)代碼,而是DLL中所要調(diào)用的函數(shù)的內(nèi)存地址,這樣當(dāng)一個(gè)或多個(gè)應(yīng)用程序運(yùn)行時(shí)再把程序代碼和被調(diào)用的函數(shù)代碼鏈接起來(lái),從而節(jié)省了內(nèi)存資源。從上面的說(shuō)明可以看出,DLL文件必須隨應(yīng)用程序一起發(fā)行,否則應(yīng)用程序?qū)?huì)產(chǎn)生錯(cuò)誤。
加載方法編輯
直接加入
在VC中打開File View一頁(yè),選中工程名,單擊鼠標(biāo)右鍵,然后選中"Add Files to Project"菜單,在彈出的文件對(duì)話框中選中要加入DLL的LIB文件即可。
設(shè)置
打開工程的 Project Settings菜單,選中Link,然后在Object/library modules下的文本框中輸入DLL的LIB文件。
程序代碼
加入預(yù)編譯指令#pragma comment (lib,"*.lib"),這種方法優(yōu)點(diǎn)是可以利用條件預(yù)編譯指令鏈接不同版本的LIB文件。因?yàn)椋贒ebug方式下,產(chǎn)生的LIB文件是Debug版本,如Regd.lib;在Release方式下,產(chǎn)生的LIB文件是Release版本,如Regr.lib。
當(dāng)應(yīng)用程序?qū)LL的LIB文件加載后,還需要把DLL對(duì)應(yīng)的頭文件(*.h)包含到其中,在這個(gè)頭文件中給出了DLL中定義的函數(shù)原型,然后聲明。
詳解
節(jié)的概念編輯
Lib格式只有四種類型的節(jié)(Section),即First Sec,Second Sec,Longname Sec和Obj Sec;其中Second Sec與Longname Sec是可選節(jié),很多Lib文件中都沒有。而開頭的Singature只是一個(gè)標(biāo)識(shí),它相當(dāng)于COFF目標(biāo)文件中的魔法數(shù)字。它是一個(gè)長(zhǎng)度為8的字符串,值為“!arch\n”。
First Sec 顧名思義,就是第一個(gè)節(jié)。它包含了庫(kù)中所有的符號(hào)名以及這些符號(hào)所在的目標(biāo)文件在庫(kù)中的位置(絕對(duì)偏移)。
Second Sec 就是第二節(jié)。它的內(nèi)容和First Sec是相同的。不同的是,Second Sec是一個(gè)有序表,通過它來(lái)查找?guī)熘械姆?hào)比通過First Sec來(lái)查找要快很多。
Longname Sec 是長(zhǎng)名稱節(jié)。這一節(jié)是一個(gè)字符串表。它包含了所有長(zhǎng)目標(biāo)文件名。如果后面的Obj Sec中沒有給出相應(yīng)的目標(biāo)文件名,我們就要到這一節(jié)中來(lái)查找。
Obj Sec 就是目標(biāo)文件節(jié)。這些節(jié)中存儲(chǔ)著不同的目標(biāo)文件的原始數(shù)據(jù)。
在庫(kù)文件中,每一節(jié)都有兩個(gè)部分。一個(gè)部分是頭,另一個(gè)部分才是該節(jié)的數(shù)據(jù);數(shù)據(jù)緊跟在頭的后面。頭描述了該節(jié)數(shù)據(jù)的類型、長(zhǎng)度等信息。這些頭的格式都是相同的。其結(jié)構(gòu)用C語(yǔ)言描述如下:
typedef struct {
char Name[16]; // 名稱
char Time[12]; // 時(shí)間
char UserID[6]; // 用戶ID
char GroupID[6]; // 組ID
char Mode[8]; // 模式
char Size[10]; // 長(zhǎng)度
char EndOfHeader[2];// 結(jié)束符
} SectionHeader;
可以看到,頭中的數(shù)據(jù)全都是字符串。用字符串的好處是可以提高格式的兼容性,因?yàn)樵诓煌臋C(jī)器上,數(shù)據(jù)的排列方式是不同的。有的機(jī)器是以Little-Endian方式工作,還有的是以Big-Endian方式工作,它們互不兼容(這兩種方式的區(qū)別???請(qǐng)看我的《COFF格式》一文,其中的文件頭一節(jié)有說(shuō)明)。用字符串就不會(huì)有這種問題(后面我們將會(huì)遇到)。但它也有不方便的地方,就是必須把字符串轉(zhuǎn)換成數(shù)值,多了一個(gè)步驟。
在這個(gè)結(jié)構(gòu)中,最常用的Name、Size以及EndOfHeader三個(gè)成員。Name就是節(jié)的名稱啦!Size也很好理解,就是該節(jié)數(shù)據(jù)的長(zhǎng)度。其內(nèi)容為“`\n”(注意,這里沒有打錯(cuò),是兩個(gè)字符“`”和“\n”)。怎么樣?有點(diǎn)奇怪吧?為什么要有這個(gè)結(jié)束符?每一節(jié)的頭長(zhǎng)度一定,每節(jié)中的數(shù)據(jù)長(zhǎng)度也知道。按順序向下讀不行嗎?答案是:不行!因?yàn)槊恳还?jié)之間存在間隙!通常是一個(gè)字節(jié)或零個(gè)字節(jié)。如果是零個(gè)字節(jié)倒好,按順序向下讀是OK的??墒侨绻粸榱愕脑?,這樣讀就要錯(cuò)位了。要知道錯(cuò)位沒有,只好用一個(gè)結(jié)束符來(lái)定位了。如果在讀頭的時(shí)候發(fā)現(xiàn)結(jié)束符不對(duì),那就要一個(gè)字節(jié)一個(gè)字節(jié)地向下查找,直到找到結(jié)束符,才能算是對(duì)齊了。切記!切記!
當(dāng)然,通過First Sec或Second Sec中給出的偏移來(lái)讀數(shù)據(jù)就不存在這個(gè)問題。不會(huì)發(fā)生錯(cuò)位,放心讀吧!
First Sec
第一節(jié),通常就是Lib中的每一個(gè)小節(jié)。它的名稱是“/”。其數(shù)據(jù)部分的結(jié)構(gòu)如下:
typedef struct {
unsigned long SymbolNum; // 庫(kù)中符號(hào)的數(shù)量
unsigned long SymbolOffset[n]; // 符號(hào)所在目標(biāo)節(jié)的偏移
char StrTable[m]; // 符號(hào)名稱字符串表
}FirstSec;
第一個(gè)成員SymbolNum是符號(hào)的數(shù)量。注意!它是以Big-Endian方式儲(chǔ)存的(x86平臺(tái)上的數(shù)據(jù)是以Little-Endian方式儲(chǔ)存的。這里應(yīng)該注意轉(zhuǎn)換。后面給出的convert函數(shù)可以在Little-Endian格式與Big-Endian格式之間進(jìn)行相互轉(zhuǎn)換)。
第二個(gè)成員SymbolOffset是一個(gè)數(shù)組,它的長(zhǎng)度n就是符號(hào)的數(shù)量,也就是SymbolNum。這個(gè)數(shù)組儲(chǔ)存了每一個(gè)符號(hào)所在的目標(biāo)節(jié)的偏移。我們可以方便地通過它來(lái)查找符號(hào)所在的目標(biāo)文件。注意!它也是以Big-Endian格式儲(chǔ)存的。
第三個(gè)成員StrTable是一個(gè)字符串表,它的長(zhǎng)度m就是SectionHeader.Size的值減去(SymbolNum+1)*4。其結(jié)構(gòu)很簡(jiǎn)單,就是一堆以‘\0’結(jié)尾的字符串(和COFF文件中的字符串表結(jié)構(gòu)相同)。在有的系統(tǒng)中,它還可能是以“/\n”這兩個(gè)字符結(jié)尾的字符串的集合。
很簡(jiǎn)單的一個(gè)結(jié)構(gòu),不過有兩個(gè)成員的長(zhǎng)度是不定的。怎么才能方便地從Lib中讀出這些數(shù)據(jù),留給大家自己想吧!下面我只給出一個(gè)進(jìn)行Little-Endian與Big-Endian互轉(zhuǎn)的函數(shù)。
inline void convert(void * p // 要轉(zhuǎn)換的數(shù)據(jù)的指針
,size_tsize = 4 // 數(shù)據(jù)的長(zhǎng)度,long為4,short為2
) {
char * buf=(char*)p;
char temp;
for ( size_t i=0;isize/2;i++ ) {
temp=buf[i];
buf[i]=buf[size-i-1];
buf[size-i-1]=temp;
}
}
Second Sec
第二節(jié)
這一節(jié)與第一節(jié)很相似!它通常也就是Lib文件的第二個(gè)節(jié)。它的名字也是“/”(注意:文件中第一個(gè)叫“/”的節(jié)是第一節(jié),第二個(gè)就是第二節(jié))。不過它的結(jié)構(gòu)與第一節(jié)有些不同,如下:
typedef struct {
unsigned long ObjNum; // Obj Sec的數(shù)量
unsigned long ObjOffset[x]; // 每一個(gè)Obj Sec的偏移
unsigned long SymbolNum; // 庫(kù)中符號(hào)的數(shù)量
unsigned short SymbolIdx[n]; // 符號(hào)在ObjOffset表中的索引
char StrTable[m]; // 符號(hào)名稱字符串表
}SecondSec;
第一個(gè)成員ObjNum是庫(kù)中Obj Sec的數(shù)量。
第二個(gè)成員ObjOffset是一個(gè)偏移表,它記錄了庫(kù)中所有Obj Sec的偏移。這個(gè)表的記錄數(shù)x就是ObjNum。
第三個(gè)成員SymbolNum與First Sec中的SymbolNum意義相同。
第四個(gè)成員SymbolIdx變成了一個(gè)索引,它記錄了相應(yīng)名稱字符串在ObjOffset這個(gè)表中的位置,我們要通過兩次索引才能找到我們所要符號(hào)的Obj Sec位置。它的項(xiàng)目數(shù)n為SymbolNum。但請(qǐng)注意,這個(gè)索引是unsigned short型,不再是unsigned long型。
第五個(gè)成員StrTable結(jié)構(gòu)與First Sec中的一樣。不過,它的長(zhǎng)度m為SectionHeader.Size的值減去((ObjNum+1)*4+(SymbolNum+2)*2)。
值得注意的是,這里的所有數(shù)據(jù)都是Little-Endian格式的。千萬(wàn)不要弄錯(cuò)了!Longname Sec
這個(gè)小節(jié)就是一個(gè)字符串表,它的名稱為“//”,其結(jié)構(gòu)同F(xiàn)irstSec.StrTable。這里就不多說(shuō)了。
Obj Sec
這一節(jié)中的數(shù)據(jù)就是COFF文件的原始數(shù)據(jù),把它讀出來(lái)存成文件,就是一個(gè)COFF文件。它的格式請(qǐng)參考《COFF格式》一文。
要指出的是它的命名方式有些特殊。如果Obj文件的名稱少于16個(gè)字符,它就會(huì)被保存在SectionHeader的Name成員中,以‘/’字符結(jié)尾。如果無(wú)法保存在Name成員中,則Name成員的第一個(gè)字符就為‘/’,之后再跟上這個(gè)名稱在Longname Sec中的偏移。
例如:
!arch\n
……
LongName Sec:
This_Is_Long_Name0001\0
This_Is_Long_Name0002\0
……
Obj Sec1:
Name[16]:“shortname/”
……
Obj Sec2:
Name[16]:“/0” // 這里使用了第一個(gè)長(zhǎng)文件名This_Is_Long_Name0001
……
Obj Sec3:
Name[16]:“/22” // 這里使用了第二個(gè)長(zhǎng)文件名This_Is_Long_Name0002
bin在c語(yǔ)言是二進(jìn)制文件。
bin既是二進(jìn)制文件,而exe則是PE文件編譯鏈接的過程是:源代碼-(編譯)-[段落的]二進(jìn)制代碼-(鏈接)-PE文件要得到二進(jìn)制文件,則只需執(zhí)行編譯的過程即可。建議你用TC,即16位的C/C++編譯器,這樣的編譯器編譯的程序不會(huì)像32位的程序那樣有很多的區(qū)塊!
數(shù)據(jù)庫(kù)中二進(jìn)制文件的高速存取方式:
圍繞二進(jìn)制文件基于數(shù)據(jù)庫(kù)存取存在速度慢、占用資源多的問題,通過對(duì)BS上傳文件原理的分析,通過數(shù)據(jù)與文件分開存儲(chǔ),文件切割上傳的方法實(shí)現(xiàn)二進(jìn)制文件基于數(shù)據(jù)庫(kù)的高速存取。
對(duì)于文件類資料保存到數(shù)據(jù)庫(kù)中,使用分塊傳輸與存儲(chǔ)可以有效提高應(yīng)用效率,另外通過測(cè)試關(guān)系型數(shù)據(jù)庫(kù)和文件型數(shù)據(jù)庫(kù)對(duì)此類應(yīng)用的性能,發(fā)現(xiàn)文件類數(shù)據(jù)庫(kù)的性能優(yōu)勢(shì)比較明顯。
1、使用fopen、fread、fwrite等C語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的文件I/O函數(shù)即可對(duì)文件進(jìn)行打開、讀取、寫入操作。下面的程序創(chuàng)建一個(gè).bin的文件,然后再?gòu)睦锩孀x取數(shù)據(jù)。
#include?stdio.h
int?main()
{
FILE*?pFile;
float?buffer[]?=?{?2.0?,?3.0?,?8.0?};
pFile?=?fopen("myfile.bin"?,?"wb");?//?打開文件寫操作
fwrite(buffer?,?1?,?sizeof(buffer)?,?pFile);?//?把浮點(diǎn)數(shù)組寫到文件?myfile.bin
fclose(pFile);?//?關(guān)閉文件
float?read[3];
pFile?=?fopen("myfile.bin"?,?"rb");?//?重新打開文件讀操作
fread(read?,?1?,?sizeof(read)?,?pFile);?//?從文件中讀數(shù)據(jù)
printf("%f\t%f\t%f\n",?read[0],?read[1],?read[2]);
fclose(pFile);?//?關(guān)閉文件
return?0;
}
2、bin文件一般是指的二進(jìn)制文件,它往往具有兩種形式,一種是某種系統(tǒng)平臺(tái)的可執(zhí)行文件格式,比如windows平臺(tái)的PE文件格式,Linux平臺(tái)的ELF文件格式,另外一種是提取的一段二進(jìn)制代碼,比如系統(tǒng)的主引導(dǎo)記錄mbr,就是一個(gè)包含512個(gè)字節(jié)的程序,用c語(yǔ)言對(duì)這類文件進(jìn)行讀取時(shí),必須按一定格式進(jìn)行解析。而且常用的方法不是使用C語(yǔ)言的I/O操作,而一般使用系統(tǒng)提供的文件內(nèi)存映射方法。