CStdioFile 的 Readstring是一行行往下讀的,
現在需要從最后一行開始讀,往上只要讀幾十行左右的資料就可以。
(檔案可能很大,可能有幾十萬行,所以從上往下讀太費勁)
該如何實作呢??? 求指點
uj5u.com熱心網友回復:
僅供參考:#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <share.h>
#include <conio.h>
int fh;
int c,r;
__int64 offset,offset1,i64,n64,l64,r64;
char ln[16000+1];
int main(int argc,char **argv) {
if (argc<2) {
fprintf(stderr,"Usage:%s filename.txt [10]\nto reverse lines of file [default the last 10 lines,-1 for all lines].\n",argv[0]);
return 1;
}
if (argc==2) n64=10i64;
if (argc>2) sscanf(argv[2],"%I64d",&n64);
fh=_sopen(argv[1],_O_BINARY|_O_RDONLY|_O_RANDOM,_SH_DENYNO);
if (-1==fh) {
fprintf(stderr,"Can not _sopen file %s!\n",argv[1]);
return 2;
}
l64=_filelengthi64(fh);if (l64==0i64) {_close(fh);return 0;}
offset=l64;
offset1=_lseeki64(fh,-1i64,SEEK_END);
if (offset1==-1i64) {_close(fh);return 3;}
i64=0i64;
while (1) {
if (_read(fh,&c,1)<1) break;//
if (('\n'==c && offset1<l64-1i64) || offset1==0i64) {
if (offset1!=0i64) offset1++;
if (_lseeki64(fh,offset1,SEEK_SET)==-1i64) break;//
r64=offset-offset1;
if (r64<=16000i64) {
r=_read(fh,ln,(unsigned int)r64);
if (r<=0) break;//
} else {
r=16000;
while (1) {
if (r64>(__int64)r) {
r64-=(__int64)r;
if (1i64==r64 || 2i64==r64) {
r=8000;
r64+=(__int64)r;
}
} else {
r=(int)r64;
r64=0i64;
}
r=_read(fh,ln,r);
if (r<=0) break;//
if (0i64==r64) break;//
ln[r]=0;
printf("%s",ln);
r=16000;
}
if (r<=0) break;//
}
ln[r]=0;
if (r>=2 && ln[r-1]=='\n' && ln[r-2]=='\r') {ln[r-2]='\n';ln[r-1]=0;r--;}//避免輸出重定向到檔案時行尾多出'\r'
if (i64==0I64) {
if ('\n'!=ln[r-1]) printf("%s\n",ln);
else printf("%s",ln);
} else {
printf("%s",ln);
}
i64++;
if ((i64%10000)==0) cprintf("\r%I64d/%I64d",offset1,l64);
if (n64>0i64 && i64>=n64) break;//
offset=offset1;
_lseeki64(fh,offset1-2i64,SEEK_SET);
offset1-=2i64;
} else {
_lseeki64(fh,-2i64,SEEK_CUR);
offset1--;
}
}
_close(fh);
return 0;
}
uj5u.com熱心網友回復:
定義位置變數P1,P2檔案指標移動到檔案結尾,
讀出段資料固定大小資料,P2指向末尾
尋找\r\n 為P1
從P1處讀取到P2
令P2=P1,繼續讀前一行
塊沒有資料,再讀出一塊,注意要讀出的塊要適當的重疊
uj5u.com熱心網友回復:
趙老師,能不能講講思路,我看您一上來大段大段的代碼,新人接受起來好難。
uj5u.com熱心網友回復:
獲取檔案大小 位元組,用win32 api 檔案操作。設定讀取指標SetFilePointer 檔案大小 -你需要讀取的尾部資料大小。
讀出尾部塊。
uj5u.com熱心網友回復:
好像有個陳述句可以跳到檔案末尾的,然后計算一下往前需要多少行在讀行嗎uj5u.com熱心網友回復:
代碼功能歸根結底不是別人幫自己看或講解或注釋出來的;而是被自己靜下心來花足夠長的時間和精力親自動手單步或設斷點或對執行到某步獲得的中間結果顯示或寫到日志檔案中一步一步分析出來的。
提醒:再牛×的老師也無法代替學生自己領悟和上廁所!
單步除錯和設斷點除錯(VS IDE中編譯連接通過以后,按F10或F11鍵單步執行,按Shift+F11退出當前函式;在某行按F9設斷點后按F5執行停在該斷點處。)是程式員必須掌握的技能之一。
查MSDN是Windows程式員必須掌握的技能之一。
在我眼里,凡是不超過1000行的代碼,寫注釋或用文字/口頭解釋都是多余!
uj5u.com熱心網友回復:
命令列解釋器概述命令列解釋器是一個單獨的軟體程式,它可以在用戶和作業系統之間提供直接的通訊。非圖形命令列解釋器用戶界面提供運行基于字符的應用程式和實用程式的環境。通過使用類似于 MS-DOS 命令解釋程式 Command.com 的單獨字符,命令列解釋器執行程式并在螢屏上顯示其輸出。Windows 服務器作業系統命令列解釋器使用命令解釋程式 Cmd.exe(該程式加載應用程式并指導應用程式之間的資訊流動)將用戶輸入轉換為作業系統可理解的形式。
可以使用命令列解釋器創建和編輯可自動執行常規任務的批處理檔案(也稱作腳本)。例如,可以使用腳本自動管理用戶帳戶或夜間備份。還可以使用 Windows 腳本宿主 CScript 的命令列版本在命令列解釋器中運行更高級的腳本。詳細資訊,請參閱運行 Windows 腳本宿主。通過使用批處理檔案來執行操作,可比使用用戶界面更有效率。批處理檔案接受命令列上可用的所有命令。有關批處理檔案和腳本的詳細資訊,請參閱使用批處理檔案。
您可以自定義命令提示符視窗以易于查看并增強對程式運行方式的控制。有關自定義命令提示符視窗的詳細資訊,請參閱配置命令提示符。
使用命令語法
語法按命令及所帶引數必須遵循的鍵入順序出現。下面的 xcopy 命令示例顯示了各種語法文本格式:
xcopy Source [Destination] [/w] [/p] [/c] [/v] [/q] [/f] [/l] [/g] [/d[:MM-DD-YYYY]] [/u] [/i] [/s [/e]] [/t] [/k] [/r] [/h] [{/a | /m}] [/n] [/o] [/x] [/exclude:File1[+[File2]][+[File3]] [{/y | /-y}] [/z]
下表說明如何解釋不同的文本格式。
格式化圖例
格式 含義
斜體 用戶必須提供的資訊
粗體 用戶必須準確鍵入的要顯示的元素
省略號(...) 在命令列中可多次重復的引數
中括號([]) 可選項
大括號({});選項用豎線(|)分隔。例如:{even|odd} 用戶必須從選項集合中選擇一個
Courier字體 代碼或程式輸出
使用多個命令和條件處理符號
使用條件處理符號可以在單個命令列或腳本中運行多個命令。通過條件處理符號運行多個命令時,條件處理符號右邊的命令根據條件處理符號左邊命令的執行結果來發揮作用。例如,只有在前一個命令失敗的情況下才可能需要運行一個新命令。或者,只有在前一個命令成功時才可能需要運行一個新命令。
可以使用下表列出的特殊字符來傳遞多個命令。
字符 語法 定義
& [...] Command1 & Command2 用來分隔一個命令列中的多個命令。Cmd.exe 運行第一個命令,然后運行第二個命令。
&& [...] Command1 && Command2 只有在符號 && 前面的命令成功時,才運行該符號后面的命令。Cmd.exe 運行第一個命令,然后只有在第一個命令運行成功時才運行第二個命令。
|| [...] Command1 || Command2 只有在符號 || 前面的命令失敗時,才運行符號 || 后面的命令。Cmd.exe 運行第一個命令,然后只有在第一個命令未能運行成功(接收到大于零的錯誤代碼)時才運行第二個命令。
( ) [...] (Command1 & Command2) 用來分組或嵌套多個命令。
;或者, Command1 Parameter1;Parameter2 用來分隔命令引數。
注意
“與”符號 (&)、管道符號 (|) 以及括號 () 是特殊字符,將它們作為引數傳遞時,必須在其前面加上轉義字符 (^) 或引號。
如果某個命令成功完成操作,該命令就回傳零 (0) 退出代碼或不回傳任何退出代碼。有關退出代碼的詳細資訊,請參閱 Microsoft Windows 部署和資源工具包。
嵌套命令列解釋器
通過在命令提示符下打開新的 Cmd.exe 實體,可以在 Cmd.exe 內嵌套命令列解釋器。默認情況下,Cmd.exe 的每個實體繼承其父 Cmd.exe 應用程式的環境。通過嵌套 Cmd.exe 的實體,可以更改區域環境,而不會影響 Cmd.exe 的父應用程式。這使您能夠保留 Cmd.exe 的原始環境,并在終止嵌套的命令列解釋器之后回傳到原始環境。但是在嵌套的命令列解釋器中所做的更改將不會被保存。
要嵌套命令列解釋器,請在命令提示符下鍵入:
cmd
出現類似于下面內容的訊息:
Microsoft (R) Windows Server 2003 Standard Edition (TM)
(C) 著作權所有 1985-2002 Microsoft Corp.
要關閉嵌套的命令列解釋器,請鍵入 exit。
使用 setlocal 和 endlocal 命令,可以在 Cmd.exe 的實體中(或在腳本中)進一步將更改區域化。Setlocal 創建區域作用范圍,而 endlocal 終止區域作用范圍。在 setlocal 和 endlocal 作用范圍內所做的更改將會被放棄,從而保持原始環境不變。這兩個命令的嵌套最高可達到 32 級。有關 setlocal 和 endlocal 命令的詳細資訊,請參閱 Setlocal 和 Endlocal。
將環境變數與 Cmd.exe 一起使用
Cmd.exe 命令列解釋器環境由確定命令列解釋器和作業系統行為的變數進行定義。可以使用兩種型別的環境變數(系統和區域)來定義命令列解釋器環境或整個作業系統環境的行為。系統環境變數定義全域作業系統環境的行為。區域環境變數定義 Cmd.exe 當前實體環境的行為。
系統環境變數預置于作業系統之中,并可用于所有 Windows 服務器作業系統行程。只有具有管理憑據的用戶才可以更改系統變數。這些變數最常用于登錄腳本。
區域環境變數只有在創建變數時針對的目標用戶登錄到計算機時才有效。HKEY_CURRENT_USER 配置單元中設定的區域變數只對當前用戶有效,但它們可定義全域作業系統環境的行為。
下表按優先順序的降序描述變數的各種型別:
1.內置系統變數
2.在 HKEY_LOCAL_MACHINE 配置單元中找到的系統變數
3.在 HKEY_CURRENT_USER 配置單元中找到的區域變數
4.在 Autoexec.bat 檔案中設定的所有環境變數和路徑
5.在登錄腳本(如果有的話)中設定的所有環境變數
6.在腳本或批處理檔案中互動使用的變數
在命令列解釋器中,Cmd.exe 的每個實體都繼承其父應用程式的環境。因此,可以在不影響父應用程式環境的情況下更改新的 Cmd.exe 環境中的變數。
下表列出 Windows server operating system 的系統和本地環境變數。
變數 型別 描述
%ALLUSERSPROFILE% 本地 回傳“所有用戶”組態檔的位置。
%APPDATA% 本地 回傳默認情況下應用程式存盤資料的位置。
%CD% 本地 回傳當前目錄字串。
%CMDCMDLINE% 本地 回傳用來啟動當前的Cmd.exe的準確命令列。
%CMDEXTVERSION% 系統 回傳當前的“命令處理程式擴展”的版本號。
%COMPUTERNAME% 系統 回傳計算機的名稱。
%COMSPEC% 系統 回傳命令列解釋器可執行程式的準確路徑。
%DATE% 系統 回傳當前日期。使用與date/t命令相同的格式。由Cmd.exe生成。有關date命令的詳細資訊,請參閱Date。
%ERRORLEVEL% 系統 回傳上一條命令的錯誤代碼。通常用非零值表示錯誤。
%HOMEDRIVE% 系統 回傳連接到用戶主目錄的本地作業站驅動器號。基于主目錄值而設定。用戶主目錄是在“本地用戶和組”中指定的。
%HOMEPATH% 系統 回傳用戶主目錄的完整路徑。基于主目錄值而設定。用戶主目錄是在“本地用戶和組”中指定的。
%HOMESHARE% 系統 回傳用戶的共享主目錄的網路路徑。基于主目錄值而設定。用戶主目錄是在“本地用戶和組”中指定的。
%LOGONSERVER% 本地 回傳驗證當前登錄會話的域控制器的名稱。
%NUMBER_OF_PROCESSORS% 系統 指定安裝在計算機上的處理器的數目。
%OS% 系統 回傳作業系統名稱。Windows2000顯示其作業系統為Windows_NT。
%PATH% 系統 指定可執行檔案的搜索路徑。
%PATHEXT% 系統 回傳作業系統認為可執行的檔案擴展名的串列。
%PROCESSOR_ARCHITECTURE% 系統 回傳處理器的芯片體系結構。值:x86或IA64(基于Itanium)。
%PROCESSOR_IDENTFIER% 系統 回傳處理器說明。
%PROCESSOR_LEVEL% 系統 回傳計算機上安裝的處理器的型號。
%PROCESSOR_REVISION% 系統 回傳處理器的版本號。
%PROMPT% 本地 回傳當前解釋程式的命令提示符設定。由Cmd.exe生成。
%RANDOM% 系統 回傳0到32767之間的任意十進制數字。由Cmd.exe生成。
%SYSTEMDRIVE% 系統 回傳包含Windowsserveroperatingsystem根目錄(即系統根目錄)的驅動器。
%SYSTEMROOT% 系統 回傳Windowsserveroperatingsystem根目錄的位置。
%TEMP%和%TMP% 系統和用戶 回傳對當前登錄用戶可用的應用程式所使用的默認臨時目錄。有些應用程式需要 TEMP,而其他應用程式則需要 TMP。
%TIME% 系統 回傳當前時間。使用與time/t命令相同的格式。由Cmd.exe生成。有關time命令的詳細資訊,請參閱Time。
%USERDOMAIN% 本地 回傳包含用戶帳戶的域的名稱。
%USERNAME% 本地 回傳當前登錄的用戶的名稱。
%USERPROFILE% 本地 回傳當前用戶的組態檔的位置。
%WINDIR% 系統 回傳作業系統目錄的位置。
設定環境變數
使用 set 命令創建、更改、洗掉或顯示環境變數。set 命令只更改當前解釋器環境中的變數。
要查看變數,請在命令提示符下鍵入:
set VariableName
要添加變數,請在命令提示符下鍵入:
set variablename=Value
要洗掉變數,請在命令提示符下鍵入:
set VariableName=
可以將大多數字符用作變數值,其中包括空格。如果使用特殊字符 <、>、|、& 或 ^,則必須在它們前面加上轉義字符 (^) 或引號。如果使用引號,則必須將引號作為值的組成部分,因為等號后面的任何內容都會被視為值。請考慮下列示例:
要創建變數值 new&name,請鍵入:
set varname=new^&name
要創建變數值 "new&name",請鍵入:
set varname="new&name"
如果在命令提示符下鍵入 set varname=new&name,就會出現與下面內容類似的錯誤訊息:
“'name' 不是內部或外部檔案,也不是可運行的程式或批處理檔案。”
變數名不區分大小寫。但是,set 顯示的變數與您鍵入的完全相同。可以在變數名中結合使用大寫字母和小寫字母,這樣可以使代碼更具有可讀性(例如,UserName)。
注意
單個環境變數的最大大小為 8192 位元組。
所有環境變數的大小總和(包括變數名和等號)最大為 65,536 KB。
替換環境變數值
要在命令列或腳本中啟用變數值替換,請將變數名包括在百分號之中(即,%VariableName%)。使用百分號可以確保 Cmd.exe 參考變數值,而不是進行文字比較。為變數名定義變數值之后,請將變數名包括在百分號之中。Cmd.exe 搜索該變數名的所有實體,并用定義的變數值進行替換。例如,如果創建包含不同值(例如,用戶名)的腳本,并且想要用這些值為每個用戶定義 USERNAME 環境變數,可以使用包括在百分號之中的 USERNAME 來撰寫代碼。運行此腳本時,Cmd.exe 將用變數值替換 %USERNAME%,這樣就消除了為每個用戶手動執行此任務的必要。變數替換是不可遞回的。Cmd.exe 檢查變數一次。有關變數替換的詳細資訊,請參閱 For 和 Call。
uj5u.com熱心網友回復:
現在的碼農竟然99%都不會在cmd視窗中輸入cd命令設定當前目錄為程式所在目錄,輸入程式名運行程式了!轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/89675.html
標籤:基礎類
上一篇:MFC怎樣讀取文本檔案里面的內容到串列 List (Control)
下一篇:關于CFile寫入檔案問題
