全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1311
推到 Plurk!
推到 Facebook!

怪怪字母疑惑?

尚未結案
fbiceo
一般會員


發表:6
回覆:12
積分:3
註冊:2004-08-04

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-08-07 00:57:53 IP:210.244.xxx.xxx 未訂閱
ö Ö ä ä ü 由於程式在讀取目錄時候會將這些字母讀成相對應的英文字 例如 ü -> u ö -> o 這個問題造成程式要進入有這些字母的資料夾時會出現錯誤 請教各位前輩,該如何讓程式可以正確讀取這些字母呢?
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-08-07 11:19:04 IP:59.115.xxx.xxx 未訂閱
fbiceo 您好:    將儲存或目錄名稱的變數以及處理目錄的函式,都由 char 改成 wchar_t (wide-character) 型態的應該就可以了,例如 char 宣告的資料改成以 wchar_t 來宣告,切換目錄的動作由 chdir(dirname) 改成 _wchdir(dirname) 來處理。 7 天天敲鍵盤 v 時時按滑鼠 8 發表人 - RedSnow 於 2005/08/07 11:22:13
fbiceo
一般會員


發表:6
回覆:12
積分:3
註冊:2004-08-04

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-08-07 13:37:52 IP:210.244.xxx.xxx 未訂閱
Hello RedSnow      感謝您的教學,不過我在更改套用到以下這個函式時候,紅色的部份會出現    [C++ Error] Unit1.cpp(67): E2034 Cannot convert 'wchar_t *' to 'char *'    我想這應該是這些函式本身必須要使用char 來傳值,我有什麼辦法可以解決嗎?    PS 以下這個範例是我尚未更改    void TForm1::DirFiles(AnsiString RootDir, bool chkSubDir, bool incPath) {     chdir(RootDir.c_str());  // 切換到指定目錄去        TSearchRec Sr;  // 設 Sr 為存放檔案資訊的結構變數     AnsiString FileName;  // 設定檔案名稱之用的暫存變數     char dos_name[256];        int done = FindFirst("*.*", faDirectory | faAnyFile, Sr);     while (done == 0)     {         if (!(Sr.Attr & faDirectory))   // 如果是檔案         {             if (incPath) // 如果檔名要包含路徑資料在內             {                 char curdir[MAXPATH+1];                 GetCurrentDirectory(MAXPATH, curdir); // 取得現行目錄名稱 FileName = AnsiString(curdir) "\\" Sr.Name; // 設定含路徑的檔名 } else { FileName = Sr.Name; // 設定不含路徑的檔名 } //這裡我先取得短檔名在dos_name GetShortPathName(FileName.c_str(),dos_name,1024); //使用RenameFile將原本抓的檔名改成短檔名,不過都不會改,是哪裡出問題呢? RenameFile(FileName,dos_name); Form1->Memo1->Lines->Add(FileName "\t" dos_name); // 此處設置您自己要處理的動作 } else if(chkSubDir) // 如果要檢查次目錄內的檔案 { if (Sr.Name != "." && Sr.Name != "..") // 如果不是相對目錄代碼的話 { DirFiles(Sr.Name.c_str(), true, incPath); // 如果是目錄的話就遞迴處理 chdir(String("..").c_str()); // 切換回前一層目錄 } } done = FindNext(Sr); // 找目錄中的下一個檔案 } FindClose(Sr); }
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-08-07 21:22:10 IP:218.168.xxx.xxx 未訂閱
您好:    PO程式碼的方式與版規說明請參考下面連結,煩請修改謝謝您的配合 >
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-08-08 06:27:01 IP:61.230.xxx.xxx 未訂閱
fbiceo 您好:    有關長檔名更改為短檔名的問題,因為與本題並無直接關係,因此我在您另一篇討論文章中做了回覆,請您到該篇查看: 目錄下的檔案名稱改成短檔名 http://delphi.ktop.com.tw/topic.php?topic_id=75660 有關您這一篇的問題,我做了一些測試,所有動作在變更資料型態為 wchar_t,以及將相關處理函式改為使用 wchar_t 資料型態的函式後,大致上都可以正常運作,目前尚餘一處未能解決,問題發生在取得短檔名的那個函式無法取得以您本篇所述那些字元所命名的檔案的短檔名,一晚上沒睡覺的結果還是沒測出來,可能是睡眠不足碰到盲點了,等我補足睡眠後,再繼續試吧。 7 天天敲鍵盤 v 時時按滑鼠 8
fbiceo
一般會員


發表:6
回覆:12
積分:3
註冊:2004-08-04

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-08-08 12:28:42 IP:59.104.xxx.xxx 未訂閱
RedSnow您好      首先謝謝您,造成您體力上的耗損,再一次至上謝意    目前已解決長改短檔名的問題,不過當資料夾有這些怪字元時就會出現錯誤    我發現是因為 TSearchRec Sr這個結構所包含Sr.Name的type是AnsiString     所以抓到的字母存在Sr.Name時會把 ü -> u 或 ö -> o,以致於程式在切換目錄會找不到路徑    再一次謝謝您所提供的程式碼,當初沒把您的名子加上實在是因為突然找不到    謝謝您可以幫我很多忙    目前若是讓DirFiles這個函式讀取到ü或ö這些特殊字元時,程式會自動終止,因為他把ü -> u 或 ö -> o 造成chdir時候會無法找到路徑,因為Sr.Name型態是AnsiString所以儲存的時候沒辦法正確儲存這些怪怪字元    我有準備一個壓縮檔,裡面包含這些特殊字元的資料夾,若您方便的話請您用這個測試看看    http://fbidata.myftp.org/program/error.rar 再一次謝謝您
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-08-08 18:34:07 IP:59.115.xxx.xxx 未訂閱
fbiceo 您好:    因為要處理的對象必須要使用 Wide-String 來處理,因此整個自定函式幾乎全部重新寫過,以下程式已經可以讀取以歐語字元設定的目錄,同時也可以對以相同狀況命名的檔案做更名處理,目前尚有兩個美中不足之處,一是目前使用的 Memo 元件無法正常顯示含有歐語字元的字樣,二是更名後的短檔名也無法保留歐語字元,前者我個人認為可以自己撰寫或是找尋第三方元件來解決,後者似乎是視窗系統本身的處理方式 (在 DOS 視窗下 dir /x 指令查看這類檔案的短檔名時,一樣會轉為大寫英文字母),除非有其它的 API 能提供解決之道,否則應該無解。 以下是我測試後修改過的版本,我拿您提供的檔案試過,各層目錄均可讀取,檔案也可正確的做更名處理,您試試看吧:
呼叫方式:
AnsiString dstr = "C:\\tmp\\error";
wchar_t dir[MAXPATH];
dstr.WideChar(dir, dstr.WideCharBufSize());    DirFiles(dir, true, false);    函式內容:
void TForm1::DirFiles(wchar_t *RootDir, bool chkSubDir, bool incPath)
{
    wchar_t curdir[MAXPATH 1];
    _wchdir(RootDir);  // 切換至指定的目錄
    _wgetcwd(curdir, MAXPATH);  // 取得切換目錄後的完整路徑名稱,並設給 curdir        wchar_t FileName[MAXPATH] ={0};  // 存放短檔名之用
    wchar_t dos_name[MAXPATH] ={0};  // 存放短檔名之用
    wchar_t allfiles[4] = {'*', '.', '*', 0x00};  // wildcard "*.*"
    wchar_t updir[3] = {'.', '.', 0x00};  // 上層目錄代碼 ".."
    wchar_t thisdir[2] = {'.', 0x00};  // 本層目錄代碼 "."
    wchar_t dirs[2] = {'\\', 0x00};  // 目錄分隔符號 "\"
    wchar_t tab[2] = {'\t', 0x00};  // Tab 符號 "\t"
    struct _wffblk ffblk;  // 存放檔案資訊的結構資料        int done = _wfindfirst(allfiles, &ffblk, FA_DIREC);  // 找尋目錄內所有檔案與目錄        while (done == 0) {  // 如果有找到符合的檔案或目錄
        wchar_t ostr[MAXPATH];
        wcscpy(ostr, (wchar_t*)ffblk.ff_name);  // 將找到的檔案或目錄名稱設給 ostr            if (!(ffblk.ff_attrib & FA_DIREC)) {  // 如果是不是目錄則視為檔案
            ZeroMemory(&FileName, sizeof(FileName));
            if (incPath) {  // 如果檔名要包含路徑資料在內
                wcscpy(FileName, curdir);
                wcscat(FileName, dirs);
                wcscat(FileName, ostr);
            } else {
                wcscpy(FileName, ostr);
            }                ZeroMemory(&dos_name, sizeof(dos_name));
            GetShortPathNameW(FileName, dos_name, MAXPATH);  // 取得短檔名並設給 dos_name                if(dos_name[0] != 0){  // 如果有短檔名資訊
                wchar_t newname[MAXPATH];
                wcscpy(newname, dos_name);
                if(wcscmp(ostr, newname) != 0){  // 長檔名與短檔名不相同時
                    CharLowerW(newname);  // 更改短檔名的名稱為小寫字樣
                    _wrename(ostr, newname);  // 更改檔案名稱為短檔名
                }
            }                wcscat(FileName, tab);
            wcscat(FileName, dos_name);                Memo1->Lines->Add(FileName);  // 顯示長檔名與短檔名
        } else if (chkSubDir) {  // 如果要檢查次目錄內的檔案
            if (wcscmp(ostr, thisdir) != 0 && wcscmp(ostr, updir) != 0) {  // 如果不是相對目錄代碼的話
                wchar_t subdir[MAXPATH];
                wchar_t fulldir[MAXPATH];
                wcscpy(subdir, ostr);
                wcscpy(fulldir, curdir);
                wcscat(fulldir, dirs);
                wcscat(fulldir, subdir);                    Memo1->Lines->Add(fulldir);  // 顯示目錄名稱                    DirFiles(fulldir, chkSubDir, incPath); // 如果是目錄的話就遞迴處理
                _wchdir(updir);
            }
        }            done = _wfindnext(&ffblk);  // 找下一個符合的目錄或檔案
    }        _wfindclose(&ffblk);
}
以上程式經多次測試修改而成,可能會殘留了一些不必要的宣告或動作,請您自行做最佳化處理。 7 天天敲鍵盤 v 時時按滑鼠 8 發表人 - RedSnow 於 2005/08/08 18:40:03
系統時間:2024-06-18 21:53:18
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!