2015年5月25日 星期一

判斷特定字串, 並改寫檔案的範例~

原本想要作到開啟一個設定檔,接著根據特定字串來直接改寫檔案

查詢了幾篇文章發現似乎無法這樣作

其中有個最主要的因素是因為:

文字檔是循序存放的,如果確定新資料與舊資料文字長度是一樣的,才可以直接作開檔、讀檔、再改寫。

舉個例子:
現在有一個設定檔login.info內容如下

username=danny
password=5566
location=taiwan

現在你想要讀出當字串為password時去改寫密碼的動作,假設你要新寫入的密碼為"123456",然後你使用直接開檔、讀檔、再改寫的方法,想必會變成下面的情形

username=danny
password=123456cation=taiwan

因為你新輸入的文字長度比舊的來的大,所以他會覆蓋到原本舊的其他的資料

=======================================================================
因此看來要改寫檔案就得用另一種方法了,這邊介紹的是,讀取原本檔案,然後寫入到另一個檔案去,沒有改寫的地方就照原本資料寫入,改寫的也一併寫入到新的資料。

最後再把原本資料砍掉,然後把新的資料改名成舊的資料名子。

詳細的範例如下所示:

首先是原始設定檔===========
devicename:dannyDevice
protocol:Bloger
resolution:HD
framerate:30



主要的程式碼部分============
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <ctype.h>

#define DEVICE_INFO_PATH "./device.info"
#define TMP_DEVICE_INFO_PATH "./tmp_device.info"

void modify_file_func()
{
        char buffer[128];

/* open login info in device. */
FILE *fptr, *fptr_tmp;
char tmp[64]={0};

        if ((fptr = fopen(DEVICE_INFO_PATH, "r")) == NULL)
        {
                printf("open_file_error");
                exit(1);
        }
else if((fptr_tmp = fopen(TMP_DEVICE_INFO_PATH, "w")) == NULL)
{
                printf("open_tmp_file_error");
                exit(1);
}

while(fgets(buffer, sizeof(buffer), fptr) != NULL)
        {
if(strstr(buffer, "protocol:"))
{
sprintf(tmp,"protocol:%s\n", 123);
fputs(tmp, fptr_tmp);
memset(tmp,'\0',sizeof(tmp));
}
else if(strstr(buffer, "resolution:"))
{
sprintf(tmp,"resolution:%s\n", 456);
fputs(tmp, fptr_tmp);
memset(tmp,'\0',sizeof(tmp));
}
else if(strstr(buffer, "framerate:"))
{
sprintf(tmp,"framerate:%s\n", 789);
fputs(tmp, fptr_tmp);
memset(tmp,'\0',sizeof(tmp));
}
else
fputs(buffer, fptr_tmp);
        }
        fclose(fptr);
fclose(fptr_tmp);
        
        //刪掉原檔案,並改寫新檔案的名子
sprintf(tmp,"rm %s;mv %s %s", DEVICE_INFO_PATH, TMP_DEVICE_INFO_PATH, DEVICE_INFO_PATH);
system(tmp);
}


int main()
{
modify_file_func();
return 0;
}


最後的device.info檔案內容=======
devicename:dannyDevice
protocol:123
resolution:456
framerate:789



2015年5月21日 星期四

shell script中判斷命令是否正確成功的作法

首先先稍微了解一下 "1>/dev/null 2>&1"

0 = standard input (stdin)
1 = standard output (stdout)
2 = standard error (stderr)

"1>/dev/null 2>&1" 首先stdout的標準輸出的訊息會先丟到/dev/null,接著stderr的訊息也一起丟到stdout也就是丟到/dev/null,所以訊息不會顯示在螢幕上。

而/dev/null,是空裝置,是一個特殊的裝置檔案,它會丟棄一切寫入其中的資料。


======================================================================

下面我們寫一個簡單的範例來練習, 用一個正確的command($ok_cmd)以及故意寫一個錯誤的command($error_cmd),指令成功會回傳1,錯誤則回傳0,執行並判斷command是否正確。

程式碼如下:
#!/bin/sh

ok_cmd='ls -al'

error_cmd='ls --al'

if $ok_cmd 1>/dev/null 2>&1; then
    echo "ok_cmd is OK!."
else
    echo "ok_cmd is ERROR!."
fi

if $error_cmd 1>/dev/null 2>&1; then
    echo "error_cmd is OK!."
else
    echo "error_cmd is ERROR!."
fi



結果輸出:



2015年5月6日 星期三

當apt_get_update時遇到問題時的解決方法 ERROR MSG:(Problem with MergeList)(status file could not be parsed or opened)

之前要作 apt-get update,當更新到最後時出現了下面的Error message:

E: Encountered a section with no Package: header
E: Problem with MergeList /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_natty_main_binary-i386_Packages
E: The package lists or status file could not be parsed or opened.

======================================================================

當遇到上面的錯誤情形時,只需要作以下幾個步驟就可以解決了:

首先叫出Terminal接著輸入以下幾個指令

1. sudo rm /var/lib/apt/lists/* -vf

2. sudo apt-get update


註:執行上面兩個指令之前,可以先將 /var/lib/apt/list/ 底下的東西全部備份,以免作了上面兩個步驟之後還是無法解決的話,可以復原 :D

如何把make時的錯誤訊息輸出到檔案

寫程式編譯的時候,有時候錯誤訊息很多

想要把所有的錯誤訊息都輸出到一個檔案,可以用下面的指令來實現~

make 2> error_msg

數字 含義 標准叫法
0 標准輸入  stdin(standard input )
1 標准輸出  stdout(standard output )
2 標准錯誤輸出  stderr(standard error)

而只下make,系統預設的是會把這三種訊息stdin、stdout、stderr都印到螢幕上。

想要將對應的信息輸出到某個檔案中,就用對應的數字加上重定向符號'>'來輸出到文件中。

下面是幾個範例:

1.想要把make輸出的全部信息,輸出到某個文件中,最常見的辦法就是:
make > error_msg 

此時預設情況是沒有改變2=stderr的輸出方式,還是輸出到螢幕,所以,如果有錯誤訊息,還是可以在螢幕上看到。


2.想要把make輸出中的錯誤與警告訊息輸出到檔案,可以使用:
make 2> error_msg

由於1=stdout沒有變,還是輸出到螢幕,所以,那些命令執行時候輸出的正常訊息,你還是可以在螢幕上看到。


3.只需要把make輸出中的正常的信息輸出到文件中(例如要看Makefile作了哪些編譯動作),可以用:
make 1> build_msg

由於2=stder沒有變,還是輸出到螢幕,所以,那些命令執行時候輸出的錯誤信息,你還是可以在螢幕上看到的。


4.想要把正常輸出信息和錯誤信息輸出到分別的文件中,可以用:
make 1> build_msg 2>error.msg 


5. 所有的信息都輸出到同一個文件中:
make > build_all_msg 2>&1 

其中的2>&1表示錯誤信息輸出到&1中,而&1,指的是前面的那個文件:build_all_msg 。

注意:上面所有的1,2等數字,後面緊跟着大於符號'>' ,中間不能有空格