C++文件的批處理


  好久沒寫文章了,今天又來做個學習C++的小總結。

 

一、統計代碼行數

  個星期前做了個統計代碼的小程序,對文件的批處理需要獲取文件列表,因為是在windows下操作的,所以百度到一個系統調用

    system("dir /a /b >> file_list.txt");

功能就是把當前目錄下的所有文件名寫到file_list.txt文件中去。這樣我就得到了所有的文件名,從而就可以對文件批處理了。對每一個文件的操作就是首先讀取文件名,然后就打開文件,接着一行一行的讀文件,沒讀取一行文件就累計代碼行數。過程很簡單,代碼如下:

 1 #include <iostream>
 2 #include <fstream>
 3 #include <cstdlib>
 4 
 5 using std::cout;
 6 using std::endl;
 7 using std::fstream;
 8 using std::string;
 9 
10 int main(int argc, char **argv)
11 {
12     //創建文件名列表文件,若存在則清空文件
13     fstream file_list("file_list.txt",std::ios::out);
14     file_list.close();
15 
16     //寫入文件名列表到file_list.txt
17     system("dir /a /b >> file_list.txt");
18     
19     long sum_code = 0;
20     fstream code_file;
21     file_list.open("file_list.txt", std::ios::in);
22     string str_line = "";
23     string t_str = "";
24     unsigned int loc = 0;//查找文件名中的"."
25     string str_last = "";
26     
27     while (!file_list.eof())
28     {
29         getline(file_list,str_line);
30         loc = str_line.find(".",0);
31 //        cout << "loc = " << loc << endl;
32         if (loc != string::npos)
33         {
34             str_last = str_line.substr(loc);
35 //            cout << "str_last = " << str_last << endl;
36         }
37         else
38         {
39             continue;
40         }
41         
42         if (str_last.compare(".h") == 0
43         || str_last.compare(".c") == 0
44         || str_last.compare(".cpp") == 0)
45         {
46             code_file.open(str_line.c_str(),std::ios::in);
47             cout << "文件名 : " << str_line << endl;
48         }
49         else
50         {
51             continue;
52         }
53         
54         //讀文件行數
55         while (!code_file.eof())
56         {
57             getline(code_file,t_str);
58             cout << t_str << endl;
59             sum_code++;
60         }
61         code_file.close();
62         cout << endl;
63     }
64     file_list.close();
65     
66     cout << "代碼行數:" << sum_code << endl;
67     system("pause");
68 
69     return 0;
70 }

二、批量刪除文件中的某一行

  天做的修改時有原因的,因為我正在將http://www.cplusplus.com/reference/做成一個chm文件(供離線查尋的文檔)。通過Teleport Ultra軟件獲取到網站的代碼后,代碼有好多是404頁面和用戶登錄頁面。這些文件我是通過手工刪除的,刪除404頁面就是根據文件大小來刪除的(不會傻到對着一千多個文件一個一個打開查看,畢竟404頁面大小是一樣的)。刪除登錄頁面是根據文件名的。文件名有new.cgi?或者edit.cgi?等等,是按文件名排序刪除的。

  后使用EasyCHM軟件開始制作。制作后出現了問題,打開頁面預覽出現

 

我郁悶了,我就打開源代碼,找到了有這么一行,打開每一文件都這樣。

因此,我就想到之前寫的代碼統計的程序了,然后我就做了個微小的修改把這一行刪除掉。在上面的55行的while中加入

if (t_str == "onPrint.print();")
{
  cout << t_str << endl;
  continue;
}

因為要修改源文件,我就通過一個臨時文件來存儲修改后的文件,文件修改完成后再將臨時文件的內容復制到源文件中,復制文件的代碼段:

        //復制回來
        out_tmp.open("tmp",std::ios::in);
        code_file.open(str_line.c_str(),std::ios::out);
        char ch;
        while(code_file && out_tmp.get(ch))
        {
            code_file.put(ch);
        }
        code_file.close();
        out_tmp.close();
        cout << "修改" << str_line << "完成" << endl;

 

全部代碼如下:

刪除指定行的代碼
 1 #include <iostream>
 2 #include <fstream>
 3 #include <cstdlib>
 4 
 5 using std::cout;
 6 using std::endl;
 7 using std::fstream;
 8 using std::string;
 9 
10 int main(int argc, char **argv)
11 {
12     //創建文件名列表文件,若存在則清空文件
13     fstream file_list("file_list.txt",std::ios::out);
14     file_list.close();
15 
16     //寫入文件名列表到file_list.txt
17     system("dir /a /b >> file_list.txt");
18     
19     long sum_code = 0;
20     fstream code_file;
21     file_list.open("file_list.txt", std::ios::in);
22     string str_line = "";
23     string t_str = "";
24     unsigned int loc = 0;//查找文件名中的"."
25     string str_last = "";
26     
27     while (!file_list.eof())
28     {
29         getline(file_list,str_line);
30         loc = str_line.find(".",0);
31 //        cout << "loc = " << loc << endl;
32         if (loc != string::npos)
33         {
34             str_last = str_line.substr(loc);
35 //            cout << "str_last = " << str_last << endl;
36         }
37         else
38         {
39             continue;
40         }
41         
42         if (str_last.compare(".htm") == 0)
43         {
44             code_file.open(str_line.c_str(),std::ios::in);
45             cout << "文件名 : " << str_line << endl;
46         }
47         else
48         {
49             continue;
50         }
51         
52         fstream out_tmp("tmp",std::ios::out);
53         //讀文件行數
54         while (!code_file.eof())
55         {
56             getline(code_file,t_str);
57             if (t_str == "onPrint.print();")
58             {
59                 cout << t_str << endl;
60                 continue;
61             }
62             out_tmp << t_str << endl;
63             sum_code++;
64         }
65         code_file.close();
66         out_tmp.close();
67         cout << endl;
68         
69         //復制回來
70         out_tmp.open("tmp",std::ios::in);
71         code_file.open(str_line.c_str(),std::ios::out);
72         char ch;
73         while(code_file && out_tmp.get(ch))
74         {
75             code_file.put(ch);
76         }
77         code_file.close();
78         out_tmp.close();
79         cout << "修改" << str_line << "完成" << endl;
80     }
81     file_list.close();
82     
83     cout << "代碼行數:" << sum_code << endl;
84     system("pause");
85 
86     return 0;
87 }

 

三、批量刪除文件中的某一代碼段

  樣對所有文件批處理后又有了新問題,彈出的腳本對話框和上面的類似。這樣慢慢刪豈不會累死,我能不能把所有的<script></<script>都刪除掉呢?我就先手動刪除一個文件的所有<script> ... </<script>。然后放到EasyCHM軟件中,結果真的好了,不彈出腳本錯誤對話框了(腳本都沒了,何來腳本錯誤呢?)。這樣我就放心了,因為腳本文件刪除了不影響htm文件的界面。這樣我就開始修改代碼了,同樣修改讀文件那一段代碼。

            if (t_str.substr(0,7) == "<script")
            {
                while (!code_file.eof() 
                        && t_str != "</script>" 
                        && t_str.substr(t_str.size()>9?t_str.size()-9:0) != "</script>")
                {
                    cout << t_str << endl;
                    getline(code_file,t_str);
                }
                cout << t_str << endl;
                getline(code_file,t_str);
            }

這是放在讀文件循環中的代碼。每次讀到一行的頭幾個字符是"<script"就對接下來的字符處理知道讀到"</script>"。因為我查了所有代碼都類似,"<script"在每行的行首,"</script>"在字符串的末尾后者行首,所以就只是簡單的判斷了下,沒有考慮到一行中既有腳本文件又有非腳本文件的情況:

<script type="text/javascript">google_ad_height = 60;</script><div id="I_midclear"></div>
</div><script type="text/javascript"src="show_ads.js" tppabs="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>

我想也不會有人會把這種代碼寫成一行吧。接着就測試了一個htm文件,結果可以了,只是有一個bug,運行一次后還殘留着<script> ... </<script>。再運行一次就清理完了。先看有bug的代碼:

有bug但是可以完成任務的代碼
 1 #include <iostream>
 2 #include <fstream>
 3 #include <cstdlib>
 4 
 5 using std::cout;
 6 using std::endl;
 7 using std::fstream;
 8 using std::string;
 9 
10 int main(int argc, char **argv)
11 {
12     //創建文件名列表文件,若存在則清空文件
13     fstream file_list("file_list.txt",std::ios::out);
14     file_list.close();
15 
16     //寫入文件名列表到file_list.txt
17     system("dir /a /b >> file_list.txt");
18     
19     long sum_code = 0;
20     fstream code_file;
21     file_list.open("file_list.txt", std::ios::in);
22     string str_line = "";
23     string t_str = "";
24     unsigned int loc = 0;//查找文件名中的"."
25     string str_last = "";
26     
27     while (!file_list.eof())
28     {
29         getline(file_list,str_line);
30         loc = str_line.find(".",0);
31 //        cout << "loc = " << loc << endl;
32         if (loc != string::npos)
33         {
34             str_last = str_line.substr(loc);
35 //            cout << "str_last = " << str_last << endl;
36         }
37         else
38         {
39             continue;
40         }
41         
42         if (str_last.compare(".htm") == 0)
43         {
44             code_file.open(str_line.c_str(),std::ios::in);
45             cout << "文件名 : " << str_line << endl;
46         }
47         else
48         {
49             continue;
50         }
51         
52         fstream out_tmp("tmp",std::ios::out);
53         //讀文件行數
54         while (!code_file.eof())
55         {
56             getline(code_file,t_str);
57             if (t_str.substr(0,7) == "<script")
58             {
59                 while (!code_file.eof() 
60                         && t_str != "</script>" 
61                         && t_str.substr(t_str.size()>9?t_str.size()-9:0) != "</script>")
62                 {
63                     cout << t_str << endl;
64                     getline(code_file,t_str);
65                 }
66                 cout << t_str << endl;
67                 getline(code_file,t_str);
68             }
69             out_tmp << t_str << endl;
70             sum_code++;
71         }
72         code_file.close();
73         out_tmp.close();
74         cout << endl;
75         
76         //復制回來
77         out_tmp.open("tmp",std::ios::in);
78         code_file.open(str_line.c_str(),std::ios::out);
79         char ch;
80         while(code_file && out_tmp.get(ch))
81         {
82             code_file.put(ch);
83         }
84         code_file.close();
85         out_tmp.close();
86         cout << "修改" << str_line << "完成" << endl;
87     }
88     file_list.close();
89     
90     cout << "代碼行數:" << sum_code << endl;
91     system("pause");
92 
93     return 0;
94 }

 

  下來就是查找bug了,然后在解決bug,記住哦,做這些操作記得備份之前原版的htm文件哦,要不然你弄完后原版的文件沒了怎么來找bug,怎么測試啊。關鍵還是看這里(循環讀文件人后再判斷的代碼段):

 1         fstream out_tmp("tmp",std::ios::out);
 2         //讀文件行數
 3         while (!code_file.eof())
 4         {
 5             getline(code_file,t_str);
 6             if (t_str.substr(0,7) == "<script")
 7             {
 8                 while (!code_file.eof() 
 9                         && t_str != "</script>" 
10                         && t_str.substr(t_str.size()>9?t_str.size()-9:0) != "</script>")
11                 {
12                     cout << t_str << endl;
13                     getline(code_file,t_str);
14                 }
15                 cout << t_str << endl;
16                 getline(code_file,t_str);
17             }
18             out_tmp << t_str << endl;
19             sum_code++;
20         }
21         code_file.close();
22         out_tmp.close();
23         cout << endl;

要修改這段代碼,需要來查看結果的,我把運行一次后的結果和原始文件對比了下,結果如下:

發現了問題,是因為執行了一次刪除腳本后,接下來的腳本緊接在其下一行,讀取的時候跳過了這一次檢查,這樣簡單啊,只執行一次判定<script>,我把if改成while就可以了,修改后的代碼如下:

最后代碼
 1 #include <iostream>
 2 #include <fstream>
 3 #include <cstdlib>
 4 
 5 using std::cout;
 6 using std::endl;
 7 using std::fstream;
 8 using std::string;
 9 
10 int main(int argc, char **argv)
11 {
12     //創建文件名列表文件,若存在則清空文件
13     fstream file_list("file_list.txt",std::ios::out);
14     file_list.close();
15 
16     //寫入文件名列表到file_list.txt
17     system("dir /a /b >> file_list.txt");
18     
19     long sum_code = 0;
20     fstream code_file;
21     file_list.open("file_list.txt", std::ios::in);
22     string str_line = "";
23     string t_str = "";
24     unsigned int loc = 0;//查找文件名中的"."
25     string str_last = "";
26     
27     while (!file_list.eof())
28     {
29         getline(file_list,str_line);
30         loc = str_line.find(".",0);
31 //        cout << "loc = " << loc << endl;
32         if (loc != string::npos)
33         {
34             str_last = str_line.substr(loc);
35 //            cout << "str_last = " << str_last << endl;
36         }
37         else
38         {
39             continue;
40         }
41         
42         if (str_last.compare(".htm") == 0)
43         {
44             code_file.open(str_line.c_str(),std::ios::in);
45             cout << "文件名 : " << str_line << endl;
46         }
47         else
48         {
49             continue;
50         }
51         
52         fstream out_tmp("tmp",std::ios::out);
53         //讀文件行數
54         while (!code_file.eof())
55         {
56             getline(code_file,t_str);
57             while (t_str.substr(0,7) == "<script")
58             {
59                 while (!code_file.eof() 
60                         && t_str != "</script>" 
61                         && t_str.substr(t_str.size()>9?t_str.size()-9:0) != "</script>")
62                 {
63                     cout << t_str << endl;
64                     getline(code_file,t_str);
65                 }
66                 cout << t_str << endl;
67                 getline(code_file,t_str);
68                     
69             }
70             out_tmp << t_str << endl;
71             sum_code++;
72         }
73         code_file.close();
74         out_tmp.close();
75         cout << endl;
76         
77         //復制回來
78         out_tmp.open("tmp",std::ios::in);
79         code_file.open(str_line.c_str(),std::ios::out);
80         char ch;
81         while(code_file && out_tmp.get(ch))
82         {
83             code_file.put(ch);
84         }
85         code_file.close();
86         out_tmp.close();
87         cout << "修改" << str_line << "完成" << endl;
88     }
89     file_list.close();
90     
91     cout << "代碼行數:" << sum_code << endl;
92     system("pause");
93 
94     return 0;
95 }

  后,我也完成了http://www.cplusplus.com/reference/離線chm版本。大家玩這個注意備份文件哦!!!

 

附件:

  [1]  統計代碼行數

  [2]  刪除htm文件中腳本代碼段

  [3] c++標准參考文檔離線chm版

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM