C:\home\SVGCats_src\src\filex.c
1|/************************************************************************** 2| 1. <<< ファイルの拡張 (FileX) >>> 3|【補足】 4|・標準ライブラリに無い特殊なファイル処理です。 5|・ファイルパスに関する処理は、StrX コンポーネントを参照してください。 6|・FILE 構造体だけでなく DOS ファイルハンドルも扱います。 7|***************************************************************************/ 8| 9|#include "mixer_precomp.h" /* Auto precompiled header, Look at mixer-... folder */ 10|// #pragma hdrstop 11| 12|#ifdef UNDER_CE /* FOR_WINCE */ 13| #error not support 14|#endif 15| 16|#if ( defined(_WIN32) || defined(FOR_DOS32) ) && !defined(__BORLANDC__) 17| //#include <windows.h> 18|#endif 19|#include <ctype.h> 20|#define STDLIBS_INCLUDE_STRING_H 21|#define STDLIBS_INCLUDE_STDLIB_H 22|#ifdef USES_MXP_AUTOINC 23| #include "filex.ah" /* Auto include header, Look at mixer-... folder */ 24|#endif 25| 26|#include <io.h> 27|#include <direct.h> 28|#include <sys\types.h> 29|#include <sys\stat.h> 30|#ifdef USES_TIMEDATE 31| #include <sys\utime.h> 32|#endif 33| 34|static char FileX_buf[1024]; 35|bool FileX_bCopyFailed = false; 36| 37| 38| 39|/*************************************************************************** 40| 2. <<< [FileX_FNames_path] ファイル名バッファ >>> 41|【補足】 42|・FileX_open したファイル名の記録です。 43|・過去 FileX_FNames_m 個のファイルの FILE* 型アドレスとファイル名を記録します。 44|***************************************************************************/ 45|#ifndef NDEBUG 46| enum { FileX_FNames_m = 30 }; 47| int FileX_FNames_i = 0; /* 次に格納する番号(ローテーションします)*/ 48| FILE* FileX_FNames_file[FileX_FNames_m]; 49| char FileX_FNames_path[FileX_FNames_m][_MAX_PATH]; 50|#endif 51| 52| 53|/*************************************************************************** 54| 3. <<< [FileX_getOpenedFName] 開いたファイル名を返す >>> 55|【引数】 56| ・FILE* fp; ファイルポインタ 57|【補足】 58|・FileX_open したファイル名のみ記録してあります。 59|***************************************************************************/ 60|char* FileX_getOpenedFName( FILE* fp ) 61|{ 62| #ifndef NDEBUG 63| int i; 64| 65| for ( i = FileX_FNames_i - 1; i != FileX_FNames_i; i-- ) { 66| if ( i < 0 ) { 67| i = FileX_FNames_m - 1; 68| if ( i == FileX_FNames_i ) 69| break; 70| } 71| if ( fp == FileX_FNames_file[i] ) 72| return FileX_FNames_path[i]; 73| } 74| if ( fp == FileX_FNames_file[i] ) 75| return FileX_FNames_path[i]; 76| 77| return "(Not Opened or Deleted from Record)"; 78| #else 79| return "(FileName not Recorded)"; 80| #endif 81|} 82| 83| 84| 85|/*************************************************************************** 86| 4. <<< [FileX_open] FILE* 型のファイルを開く >>> 87|【補足】 88|・例外付きの fopen 関数です。 89|***************************************************************************/ 90|#ifdef USES_STRX 91|FILE* FileX_open( const char* path, const char* mode ) 92|{ 93| FILE* file; 94| 95| ASSERT( path != NULL ); 96| ASSERT( *path != 0 ); 97| if ( strcmp( path, "\\\"" ) == 0 ) 98| ((char*)(path))[1] = ' '; 99| file = fopen( path, mode ); 100| if ( file == NULL ) { 101| char path2[_MAX_PATH]; 102| 103|//WS( mode ); 104| if ( strchr( mode, 'w' ) != NULL ) { 105| StrX_cpyFolder( path2, path ); 106|//WS( path2 ); 107| if ( path2[0] != '\0' && ! FileX_isDir( path2 ) ) 108| error2_1( FileX_Err_CannotWriteOpen, 109| "ファイルを格納するフォルダが無いので、ファイル \"%s\" が書きこめません", path ); 110| else 111| error2_1( FileX_Err_CannotWriteOpen, 112| "ファイル \"%s\" が書きこめません(読み込み専用属性が付いているか、" 113| "フォルダです)", path ); 114| } 115| else { 116| _getcwd( path2, sizeof(path2) ); 117| error2_2( FileX_Err_CannotReadOpen, 118| "ファイル \"%s\" が見つかりません\n" 119| "カレント=%s", path, path2 ); 120| } 121| } 122| 123| #ifndef NDEBUG 124| FileX_FNames_file[FileX_FNames_i] = file; 125| strcpy( FileX_FNames_path[FileX_FNames_i], path ); 126| FileX_FNames_i ++; 127| if ( FileX_FNames_i == FileX_FNames_m ) FileX_FNames_i = 0; 128| #endif 129| 130| return file; 131|} 132|#endif 133| 134| 135|/*************************************************************************** 136| 5. <<< [FileX_getCSV] CSV 形式の1項目を入力する >>> 137|【引数】 138| ・char* data; 項目を格納する文字列バッファ 139| ・int data_maxLen; data に格納できる最大のサイズ(\0含まず) 140|【補足】 141|・次に読み込むファイルポインタを、読み込む項目の先頭に移動してから呼び出し 142| てください。 143|・次に読み込むファイルポインタは、',' または '\n' または EOF に移ります。 144|・次の項目を読み込む前に ',' または '\n' を読み飛ばしてください。 145|【例】 146|・例1: abc,"abc,d""ef",123 (\n) なら data=[abc], ファイルポインタ = ',' 147|・例2: "abc,d""ef",123 (\n) なら data=[abc,d"ef], ファイルポインタ = ',' 148|・例3: 123 (\n) なら data=[123], ファイルポインタ = '\n' 149|***************************************************************************/ 150|void FileX_getCSV( FILE* file, char* data, int data_maxLen ) 151|{ 152| int c, c2; 153| char* data_over = data + data_maxLen; 154| 155| c = fgetc( file ); 156| 157| /* "" の間を読み込む場合 */ 158| if ( c == '"' ) { 159| c = fgetc( file ); 160| c2 = fgetc( file ); 161| while ( (c != '"' || c2 =='"') && c != EOF ) { 162| if ( data < data_over - 1 ) 163| *data++ = (char)c; 164| if ( c == '"' && c2 == '"' ) c = fgetc( file ); 165| else c = c2; 166| c2 = fgetc( file ); 167| } 168| } 169| /* , まで読み込む場合 */ 170| else { 171| while ( c != ',' && c!= '\n' && c!= EOF ) { 172| if ( data < data_over - 1 ) 173| *data++ = (char)c; 174| c = fgetc( file ); 175| } 176| ungetc( c, file ); 177| } 178| *data = '\0'; 179|} 180| 181| 182| 183|/*************************************************************************** 184| 6. <<< [FileX_skipCSV] CSV 形式の1項目をスキップする >>> 185|【補足】 186|・次に読み込むファイルポインタは、',' または '\n' または EOF に移ります。 187|・次の項目を読み込む前に ',' または '\n' を読み飛ばしてください。 188|***************************************************************************/ 189|void FileX_skipCSV( FILE* file ) 190|{ 191| char c; 192| 193| FileX_getCSV( file, &c, 0 ); 194|} 195| 196| 197| 198|/*************************************************************************** 199| 7. <<< [FileX_putCSV] CSV 形式の1項目を出力する >>> 200|【補足】 201|・必要に応じて "" で囲んだり " 文字を "" にします。 202|・','や'\n'を出力しないので、別に行ってください。 203|***************************************************************************/ 204|void FileX_putCSV( FILE* file, char* data ) 205|{ 206| bool kakomu; /* "" で囲むか */ 207| 208| kakomu = ( strchr( data, ',' ) || strchr( data, '"' ) ); 209| 210| if ( kakomu ) fprintf( file, "\"" ); 211| 212| while ( *data != '\0' ) { 213| if ( *data == '"' ) fprintf( file, "\"\"" ); 214| else fprintf( file, "%c", *data ); 215| data++; 216| } 217| 218| if ( kakomu ) fprintf( file, "\"" ); 219|} 220| 221| 222| 223|/************************************************************************ 224| 8. <<< [FileX_isExist] ファイルの存在を確かめる >>> 225|【引数】 226| ・char* fname; ファイルへのパス名 227| ・bool 返り値; ファイル or フォルダの存在 228|【補足】 229|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに 230| なります。 231|・指定したパスがフォルダに一致する場合も、true を返します。 232|*************************************************************************/ 233|#ifdef USES_STRX 234|#ifdef USES_EXCEPT3 235|bool FileX_isExist( const char* fname ) 236|{ 237| if ( strstr( fname, ".." ) != NULL ) { 238| char path[_MAX_PATH]; 239| 240| c_try { 241| StrX_getRunFullPath( path, fname, sizeof(path) ); 242| } 243| c_catch ( Errors_Msg*, err ) { 244| if ( err->code == StrX_Err_NoMoreParentDir ) 245| strcpy( path, ".." ); 246| } c_end_catch; 247| if ( strstr( path, ".." ) != NULL ) 248| return false; 249| } 250| return (_access( fname, 0 ) == 0); 251|} 252|#endif 253|#endif 254| 255|/************************************************************************ 256| 9. <<< [FileX_isDir] フォルダの存在を確かめる >>> 257|【引数】 258| ・const char* fname; フォルダへのパス名 259| ・bool 返り値; フォルダの存在 260|【補足】 261|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに 262| なります。 263|・指定したパスがファイルに一致する場合、false を返します。 264|*************************************************************************/ 265|#ifdef USES_STRX 266|bool FileX_isDir( const char* path ) 267|{ 268| struct _stat stat; 269| char path2[_MAX_PATH]; 270| 271| strcpy( path2, path ); 272| StrX_cutLastOf2( path2, '/' ); 273| StrX_cutLastOf2( path2, '\\' ); 274| if ( path2[2]== '\0' && path2[1] == ':' && isalpha( path2[0] ) ) 275| return true; 276| 277| if ( _stat( path2, &stat ) ) return false; 278| return ( stat.st_mode & _S_IFDIR ) ? true : false; 279|} 280|#endif 281| 282| 283| 284|/************************************************************************ 285| 10. <<< [FileX_getOneExistWild] ワイルドカードに一致するファイルパスを得る >>> 286|【引数】 287| ・char* wild_path; ワイルドカードを含んだファイルパス 288| ・char* first_path; 一致したパス(一致したうちの1つ)(サイズは _MAX_PATH) 289| ・int 返り値; 一致したファイルの数 290|*************************************************************************/ 291|int FileX_getOneExistWild( const char* wild_path, char* first_path ) 292|{ 293| long handle; 294| int n = 0; 295| struct _finddata_t data; 296| 297| handle = _findfirst( (char*)wild_path, &data ); 298| if ( handle != -1 ) { 299| 300| StrX_cpyFolder( first_path, wild_path ); 301| StrX_addFName( first_path, data.name ); 302| n ++; 303| 304| while ( _findnext( handle, &data ) != -1 ) 305| n++; 306| 307| _findclose( handle ); 308| } 309| 310| return n; 311|} 312| 313| 314|/************************************************************************ 315| 11. <<< [FileX_getUpdate] ファイルの更新日時を取得する >>> 316|【引数】 317| ・time_t* date; 更新日時を格納するアドレス 318|【補足】 319|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに 320| なります。 321|・ファイルが存在しない場合、動作未定義です。 322|・time_t 型は、ctime や difftime などの標準関数に使うことが出来ます。 323|*************************************************************************/ 324|#ifdef USES_STDPLUS 325|void FileX_getUpdate( const char* fName, time_t* date ) 326|{ 327| int r; 328| struct _stat status; 329| 330| r = _stat( fName, &status ); 331| if ( r != 0 ) { 332| StdPlus_printErrno(); 333| error(); 334| } 335| 336| *date = status.st_mtime; 337|} 338|#endif /* USES_STDPLUS */ 339| 340| 341| 342|/************************************************************************ 343| 12. <<< [FileX_setUpdate] ファイルの更新日時を変更する >>> 344|【引数】 345| ・time_t* date; 更新日時を格納するアドレス 346|【補足】 347|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに 348| なります。 349|*************************************************************************/ 350|#if defined(USES_STDPLUS) && defined(USES_TIMEDATE) 351|void FileX_setUpdate( const char* path, time_t* date ) 352|{ 353| struct _utimbuf tim; 354| 355| time( &tim.actime ); 356| tim.modtime = *date; 357| if ( _utime( path, &tim ) == -1 ) 358| error(); 359|} 360|#endif 361| 362| 363| 364|/************************************************************************ 365| 13. <<< [FileX_getSize] ファイルサイズを返す >>> 366|【補足】 367|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに 368| なります。 369|・使用サイズを取得するには、FileX_FreeSpc_getUseFileSize 関数を使用して 370| ください。 371|・ファイルが存在しない場合や無効なパスを指定したときは、0 を返します。 372|*************************************************************************/ 373|int FileX_getSize( const char* path ) 374|{ 375| int r; 376| struct _stat status; 377| 378| r = _stat( path, &status ); 379| if ( r != 0 ) return 0; 380| 381| return status.st_size; 382|} 383| 384|/************************************************************************ 385| 14. <<< [FileX_getSftSum] シフトチェックサムの値を返す >>> 386|【引数】 387| ・int maxFileSize; 調査する最大のファイルサイズ(-1=ファイル全部) 388|【補足】 389|・シフトチェックサムの値は、ファイルの先頭から1バイトごとに合計した値ですが、 390| ファイルアドレスを7で割った余りの分だけ左シフトしてから加算します。 391|・maxFileSize を指定すると、先頭から指定のバイト数までの合計をします。 392|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに 393| なります。 394|*************************************************************************/ 395|int FileX_getSftSum( const char* path, int maxFileSize ) 396|{ 397| FILE* f; 398| int c; 399| int sum = 0; 400| int adr = 0; 401| int adr_mod7 = 0; /* ファイルアドレスを7で割った余り */ 402| 403| f = FileX_open( path, "rb" ); 404| while ( ( c = fgetc( f ) ) != EOF && adr < maxFileSize ) { 405| sum += ( c << adr_mod7 ); 406| adr ++; 407| adr_mod7 = ( adr_mod7 == 6 ? 0 : adr_mod7 + 1 ); 408| } 409| 410| fclose( f ); 411| 412| return sum; 413|} 414| 415|/************************************************************************ 416| 15. <<< [FileX_getPathes] フォルダに入っているファイルパスを取得する >>> 417|【引数】 418| ・char* folder; フォルダパス(絶対パス) 419| ・StrX_Mem* files; ファイルパスの格納場所(初期化済みを指定) 420|【補足】 421|・絶対パスで格納します。 422|・ファイルパスは、StrX_Mem_alloc で確保した領域に格納ます。 423|*************************************************************************/ 424|#ifdef USES_FILEFIND 425|#ifdef USES_STRX 426|void FileX_getPathes( const char* folder, StrX_Mem* files ) 427|{ 428| FileFind find; 429| char* s; 430| 431| FileFind_init( &find, folder ); 432| 433| while ( FileFind_next( &find ) == 0 ) { 434| if ( ! FileFind_isDir( &find ) ) { 435| s = StrX_Mem_alloc( files ); 436| strcpy( s, folder ); s = strchr( s, '\0' ); 437| *s = '\\'; s++; 438| strcpy( s, FileFind_getFName( &find ) ); 439| } 440| } 441| FileFind_finish( &find ); 442|} 443|#endif /* USES_STRX */ 444|#endif /* USES_FILEFIND */ 445| 446| 447| 448|/************************************************************************ 449| 16. <<< [FileX_repairExt] ファイルの内容を調べて拡張子を直す >>> 450|【引数】 451| ・char* path; (入力)ファイルパス、(出力)拡張子を修正したパス 452| ・bool 返り値; ファイルタイプを識別できたかどうか 453|【補足】 454|・拡張子を修正した場合、path 変数の内容だけでなく、ファイルの名前も変わります。 455|*************************************************************************/ 456|#ifdef USES_STRX 457|bool FileX_repairExt( char* path ) 458|{ 459| FILE* f; 460| char head[16]; 461| char* ext = NULL; 462| char path2[_MAX_PATH]; 463| 464| if ( ! FileX_isExist( path ) ) return false; 465| 466| f = FileX_open( path, "rb" ); 467| fread( head, 1, sizeof(head), f ); 468| fclose( f ); 469| 470| if ( strncmp( head, "GIF", 3 ) == 0 ) ext = "gif"; 471| else if ( strncmp( head + 1, "PNG", 3 ) == 0 ) ext = "png"; 472| else if ( strncmp( head + 6, "JFIF", 4 ) == 0 ) ext = "jpg"; 473| 474| if ( ext == NULL ) return false; 475| 476| if ( stricmp( StrX_refExt( path ), ext ) != 0 ) { 477| strcpy( path2, path ); 478| StrX_chgExt( path, ext ); 479| remove( path ); 480| MoveFile( path2, path ); 481| } 482| 483| return true; 484|} 485|#endif 486| 487|/************************************************************************ 488| 17. <<< [FileX_isUpdate] ファイルが同一バージョンか判断する >>> 489|【機能】 490|・ファイルの更新日時が秒単位なのを利用して、ファイルが同一バージョンか 491| どうか判断します。 492|【引数】 493| ・const char* fName; 判断するファイル名 494| ・time_t* date; 入力は、比較対象となるバージョンの更新日付 495| 出力は、fName のファイルの更新日付 496| ・bool 返り値; 同一バージョンかどうか 497|【補足】 498|・もし、時計のずれや、頻繁な更新のために、偶然に同一時刻になった場合、 499| 正しく判断できません。 500|**************************************************************************/ 501|bool FileX_isUpdate( const char* fName, time_t* date ) 502|{ 503| bool ret; 504| int r; 505| struct _stat status; 506| 507| r = _stat( fName, &status ); 508| ASSERT( r == 0 ); 509| 510| ret = (*date == status.st_mtime ); 511| *date = status.st_mtime; 512| return ret; 513|} 514| 515| 516| 517|/************************************************************************ 518| 18. <<< [FileX_cmpTime] ファイルの更新日時を比較する >>> 519|【引数】 520| ・int 返り値; 0=等しい、0より大(>) fNameA のファイルが新しい 521| 0より小(<) fNameB のファイルが新しい 522|【補足】 523|・相対パスによって指定する場合、現在実行中のフォルダからの相対パスに 524| なります。 525|・ファイルの存在と更新日時に対する返り値の関係は次の通りです。 526| [fNameA] [更新日時] [fNameB] [返り値] 527| 存在 == 存在 0 528| 存在 > 存在 1 529| 存在 < 存在 -1 530| 存在 なし 2 531| なし 存在 -2 532| なし なし 0 533|・新しいファイルを上書きコピーするものと同じアルゴリズムを使って、 534| 新しいファイルを作る(コピーする)ことができます。 535|・引数にファイル名を指定しない場合、TimeDate_cmpTime 関数を用います。 536|*************************************************************************/ 537|#ifdef USES_STDPLUS 538|#ifdef USES_EXCEPT3 539|int FileX_cmpTime( const char* fNameA, const char* fNameB ) 540|{ 541| time_t timeA, timeB; 542| double diffTime; 543| 544| // ファイルの存在しない場合、最も古いものとして比較する 545| if ( ! FileX_isExist( fNameA ) ) { 546| if ( ! FileX_isExist( fNameB ) ) return 0; 547| else return -2; 548| } 549| else if ( ! FileX_isExist( fNameB ) ) return 2; 550| 551| // 両方のファイルの日付を比較する 552| FileX_getUpdate( fNameA, &timeA ); 553| FileX_getUpdate( fNameB, &timeB ); 554| diffTime = difftime( timeA, timeB ); 555| if ( diffTime > 0 ) return 1; 556| else if ( diffTime < 0 ) return -1; 557| else return 0; 558|} 559|#endif 560|#endif /* USES_STDPLUS */ 561| 562| 563| 564|/*********************************************************************** 565| 19. <<< [FileX_getTmpPath] テンポラリファイルのパスを作成する >>> 566|【引数】 567| ・char* prefix; ファイル名に付ける接頭辞 568| ・char* path; 作成したパスを格納するアドレス(サイズは _MAX_PATH) 569|【補足】 570|・Windows の場合、通常 c:\Windows\Temp フォルダの中のファイルへのパスを 571| 作成します。 572|************************************************************************/ 573|void FileX_getTmpPath( const char* prefix, char* path ) 574|{ 575| static char* defTmpDir = "\\"; 576| char* s; 577| 578| s = _tempnam( defTmpDir, (char*)prefix ); 579| strcpy( path, s ); 580| 581| #ifdef STDPLUS_USES_STDNAME 582| #undef free 583| #endif 584| 585| free( s ); 586| 587| #ifdef STDPLUS_USES_STDNAME 588| #define free StdPlus_free 589| #endif 590|} 591| 592| 593|/*********************************************************************** 594| 20. <<< [FileX_getTmpPath2] テンポラリファイルのパスを作成する(フォルダ指定) >>> 595|【引数】 596| ・char* prefix; ファイル名に付ける接頭辞 597| ・char* path; 作成したパスを格納するアドレス(サイズは _MAX_PATH) 598| ・char* folder; テンポラリファイルを作成するフォルダ(絶対パス) 599|************************************************************************/ 600|#ifdef USES_STRX 601|#ifdef USES_EXCEPT3 602|void FileX_getTmpPath2( const char* prefix, const char* folder, char* path ) 603|{ 604| int i = 1; 605| int bDir = FileX_isDir( folder ); 606| 607| for (;;) { 608| if ( bDir ) { 609| if ( StrX_getLast( folder ) == '\\' ) 610| sprintf( path, "%s%s%d", folder, prefix, i ); 611| else 612| sprintf( path, "%s\\%s%d", folder, prefix, i ); 613| } 614| else { 615| StrX_cpyFolder( path, folder ); 616| sprintf( strchr( path, '\0' ), "\\%s%d", prefix, i ); 617| } 618| if ( ! FileX_isExist( path ) ) return; 619| i++; 620| } 621|} 622|#endif 623|#endif 624| 625|/*********************************************************************** 626| 21. <<< [FileX_getTmpPath2] テンポラリファイルのパスを作成する(フォルダ指定) >>> 627|【引数】 628| ・char* prefix; ファイル名に付ける接頭辞 629| ・char* path; 作成したパスを格納するアドレス(サイズは _MAX_PATH) 630| ・char* folder; テンポラリファイルを作成するフォルダ(絶対パス) 631|************************************************************************/ 632|#if defined(USES_WINX) && defined(USES_STRX) && defined(USES_EXCEPT3) 633|void FileX_getTmpPath3( const char* folder, const char* prefix, const char* ext, char* path ) 634|{ 635| int i = 1; 636| bool b; 637| 638| if ( folder == NULL || ! FileX_isDir( folder ) ) { 639| folder = WinX_getTempPath(); 640| } 641| 642| b = ( StrX_getLast( folder ) == '\\' ); 643| 644| for (;;) { 645| if ( b ) 646| sprintf( path, "%s%s%d.%s", folder, prefix, i, ext ); 647| else 648| sprintf( path, "%s\\%s%d.%s", folder, prefix, i, ext ); 649| 650| if ( ! FileX_isExist( path ) ) return; 651| i++; 652| } 653|} 654|#endif 655| 656|/************************************************************************* 657| 22. <<< [FileX_isDiff] 2つのファイルの内容が同一かどうか調べる >>> 658|【引数】 659| ・int 返り値; 0=同一、 1=異なる、-1=fname1 が開けない、 660| -2=fname2 が開けない、-3=fname1,fname2 とも開けない 661|【補足】 662|・両方のファイルが存在して、内容が同一かどうかを判定するならば、 663| 返り値は bool 値(0か0以外か)として判定することができます。 664|**************************************************************************/ 665|int FileX_isDiff( const char* fNameA, const char* fNameB ) 666|{ 667| int ret; 668| FILE *file1, *file2; 669| int size1, size2; 670| static char buf1[256], buf2[256]; 671| 672| file1 = fopen( fNameA, "rb" ); 673| file2 = fopen( fNameB, "rb" ); 674| 675| if ( file1 == NULL ) { 676| if ( file2 == NULL ) return -3; 677| else { 678| fclose( file2 ); 679| return -1; 680| } 681| } 682| if ( file2 == NULL ) { 683| fclose( file1 ); 684| return -2; 685| } 686| 687| ret = 1; 688| for (;;) { 689| size1 = fread( buf1, 1, 256, file1 ); 690| size2 = fread( buf2, 1, 256, file2 ); 691| 692| if ( size1 != size2 ) break; 693| if ( memcmp( buf1, buf2, size1 ) != 0 ) break; 694| 695| if ( size1 != 256 ) { ret = 0; break; } 696| } 697| 698| fclose( file1 ); 699| fclose( file2 ); 700| 701| return ret; 702|} 703| 704| 705| 706|/************************************************************************* 707| 23. <<< [FileX_copy] ファイルをコピーする >>> 708|【補足】 709|・to_path は、フォルダ名だけでなく、ファイル名まで指定してください。 710|**************************************************************************/ 711|#if defined(USES_STDPLUS) && defined(USES_STRX) 712|#if defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE) 713|#if defined(FOR_WIN32) || defined(FOR_DOS32) 714|void FileX_copy( const char* to_path, const char* from_path ) 715|{ 716| FileX_copy2( to_path, from_path, NULL, NULL ); 717|} 718|#endif 719|#endif 720|#endif 721| 722| 723|/************************************************************************* 724| 24. <<< [FileX_copy2] ファイルをコピーする(コールバック付き) >>> 725|【引数】 726| ・FileX_CopyBack callback; 進捗状況表示のためのコールバック関数 727|【補足】 728|・to_path は、フォルダ名だけでなく、ファイル名まで指定してください。 729|・fwrite を実行するたびに callback 関数を呼び出します。 730|・書き込みに失敗した場合、エラーになり、それまでにコピーしたデータは削除されます。 731|**************************************************************************/ 732|#if defined(USES_STDPLUS) && defined(USES_STRX) 733|#if defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE) 734|#if defined(WIN32) || defined(FOR_DOS32) 735|void FileX_copy2( const char* to_path, const char* from_path, 736| FileX_CallBack callback, void* obj ) 737|{ 738| FILE* to_file; 739| FILE* from_file; 740| size_t size; 741| struct _utimbuf tim; 742| time_t date; 743| int now = 0, all; 744| DWORD attr; 745| BOOL bSuccess; 746| 747| if ( ! FileX_isExist( from_path ) ) { 748| error2_1( FileX_Err_NotFindCopySrc, "コピー元が見つかりません %s", 749| from_path ); 750| } 751| 752| /* ファイルの属性を取得する */ 753| attr = GetFileAttributes( from_path ); 754| if ( attr == 0xFFFFFFFF ) error(); 755| FileX_getUpdate( from_path, &date ); 756| all = FileX_getSize( from_path ); 757| 758| /* ファイルを開く */ 759| FileX_mkdir2( to_path, true ); 760| if ( FileX_isExist( to_path ) ) FileX_setReadOnly( to_path, false ); 761| to_file = FileX_open( to_path, "wb" ); 762| from_file = FileX_open( from_path, "rb" ); 763| 764| /* ファイルの内容をコピーする */ 765| if ( callback != NULL ) callback( obj, now, all ); 766| do { 767| size = fread( FileX_buf, 1, sizeof(FileX_buf), from_file ); 768| if ( fwrite( FileX_buf, 1, size, to_file ) != size ) { 769| fclose( to_file ); fclose( from_file ); 770| remove( to_path ); 771| FileX_bCopyFailed = true; 772| error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。", 773| to_path ); 774| } 775| now += size; 776| if ( callback != NULL ) callback( obj, now, all ); 777| } while ( size == sizeof(FileX_buf) ); 778| 779| /* ファイルを閉じる */ 780| fclose( to_file ); 781| fclose( from_file ); 782| 783| /* 更新日付やファイル属性を元のファイルと同じにする */ 784| time( &tim.actime ); 785| tim.modtime = date; 786| _utime( to_path, &tim ); 787| bSuccess = SetFileAttributes( to_path, attr ); 788| if ( ! bSuccess ) error(); 789|} 790|#endif 791|#endif 792|#endif 793| 794| 795|/************************************************************************* 796| 25. <<< [FileX_move] ファイルまたはフォルダを移動する >>> 797|【補足】 798|・from_path にフォルダのパスを指定することも出来ます。 799|・to_path は、格納するフォルダ名だけでなく、ファイル名(フォルダ名)まで 800| 指定してください。 801|・ドライブが異なる場合、コピーを実行するためパフォーマンスが落ちることがあります。 802|・移動先にファイルがある場合は上書きします。 803|・移動先にフォルダがある場合、フォルダに含まれるファイル名が一致するときのみ 804| ファイルを上書きします。 805|・書き込みに一度でも失敗した場合、データ保護のためコピー元の削除を一切 806| 行わなくなります。この状態から復元するには、FileX_bCopyFailed グローバル変数を 807| false にしてください。 808|**************************************************************************/ 809|#ifdef USES_STRX 810|#ifdef USES_STDPLUS 811|#ifdef USES_FILEFIND 812|#ifdef USES_NESTFIND 813|#ifdef USES_BIGSTACK 814|#ifdef USES_WINX 815|void FileX_move( const char* to_path, const char* from_path ) 816|{ 817| if ( MoveFile( from_path, to_path ) == 0 ) { 818| if ( FileX_isDir( from_path ) ) { 819| FileX_copyFolder( to_path, from_path, true ); 820| if ( ! FileX_bCopyFailed ) 821| FileX_removeFolder( from_path ); 822| } 823| else { 824| FileX_copy2( to_path, from_path, NULL, NULL ); 825| if ( ! FileX_bCopyFailed ) { 826| if ( remove( from_path ) == -1 ) 827| error2_1( FileX_Err_AccessDenied, "%s が削除できません", from_path ); 828| } 829| } 830| } 831|} 832|#endif 833|#endif 834|#endif 835|#endif 836|#endif 837|#endif 838| 839| 840|/************************************************************************* 841| 26. <<< [FileX_copyPickup] ファイルの一部をコピーする >>> 842|【引数】 843| ・char* to_path; コピー先(絶対パス) 844| ・char* from_path; コピー元(絶対パス) 845| ・int startPos; 開始ファイルアドレス 846| ・int endPos; 終了ファイルアドレスの次(FILEX_TO_LAST, FILEX_TO_FULLも可) 847| ・int 返り値 コピーしたファイルのサイズ 848|【補足】 849|・to_path は、フォルダ名だけでなく、ファイル名まで指定してください。 850|・endPos のアドレスの直前までコピーします。endPos のアドレスの内容はコピーしません。 851|・endPos に FILEX_TO_LAST を指定すると最後までコピーします。 852| FILEX_TO_FULL を指定するとディスクの容量をチェックしてできる限りコピーします。 853|**************************************************************************/ 854|#if defined(USES_STDPLUS) && defined(USES_STRX) 855|#if defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE) 856|#if defined(WIN32) || defined(FOR_DOS32) 857|int FileX_copyPickup( const char* to_path, const char* from_path, 858| int startPos, int endPos ) 859|{ 860| return FileX_copyPickup2( to_path, from_path, 861| startPos, endPos, NULL, NULL ); 862|} 863|#endif 864|#endif 865|#endif 866| 867| 868|/************************************************************************* 869| 27. <<< [FileX_copyPickup2] ファイルの一部をコピーする >>> 870|【引数】 871| ・char* to_path; コピー先(絶対パス) 872| ・char* from_path; コピー元(絶対パス) 873| ・int startPos; 開始ファイルアドレス 874| ・int endPos; 終了ファイルアドレスの次(FILEX_TO_LAST, FILEX_TO_FULLも可) 875| ・int 返り値 コピーしたファイルのサイズ 876|【補足】 877|・to_path は、フォルダ名だけでなく、ファイル名まで指定してください。 878|・endPos のアドレスの直前までコピーします。endPos のアドレスの内容はコピーしません。 879|・endPos に FILEX_TO_LAST を指定すると最後までコピーします。 880| FILEX_TO_FULL を指定するとディスクの容量をチェックしてできる限りコピーします。 881|**************************************************************************/ 882|#ifdef WIN32 883|#ifdef USES_STRX 884|#ifdef USES_EXCEPT3 885|#ifdef USES_BIGSTACK 886|int FileX_copyPickup2( const char* to_path, const char* from_path, 887| int startPos, int endPos, FileX_CallBack callback, void* obj ) 888|{ 889| char root_path[4]; 890| FILE* to_file; 891| FILE* from_file; 892| int size, leftSize; 893| int now = 0, all; 894| 895| if ( endPos == FILEX_TO_FULL ) { 896| FileX_FreeSpc spc; 897| 898| FileX_FreeSpc_init( &spc ); 899| strncpy( root_path, to_path, 3 ); root_path[3] = '\0'; 900| ASSERT( root_path[1] == ':' ); 901| FileX_FreeSpc_scan( &spc, root_path ); 902| endPos = startPos + FileX_FreeSpc_getFreeSize( &spc ) + 903| FileX_FreeSpc_getUseFileSize( &spc, to_path ); 904| } 905| else if ( endPos == FILEX_TO_LAST ) { 906| endPos = INT_MAX; 907| } 908| 909| all = FileX_getSize( from_path ); 910| if ( all < endPos ) all = endPos; 911| all -= startPos; 912| 913| FileX_mkdir2( to_path, true ); 914| to_file = FileX_open( to_path, "wb" ); 915| from_file = FileX_open( from_path, "rb" ); 916| 917| fseek( from_file, startPos, SEEK_SET ); 918| leftSize = endPos - startPos; 919| if ( callback != NULL ) callback( obj, now, all ); 920| do { 921| size = fread( FileX_buf, 1, sizeof(FileX_buf), from_file ); 922| if ( size > leftSize ) size = leftSize; 923| if ( fwrite( FileX_buf, 1, size, to_file ) != (unsigned)size ) { 924| fclose( to_file ); fclose( from_file ); 925| remove( to_path ); 926| FileX_bCopyFailed = true; 927| error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。", 928| to_path ); 929| } 930| leftSize -= size; 931| now += size; 932| if ( callback != NULL ) callback( obj, now, all ); 933| } while ( size == sizeof(FileX_buf) ); 934| 935| fclose( to_file ); 936| fclose( from_file ); 937| 938| return now; 939|} 940|#endif 941|#endif 942|#endif 943|#endif 944| 945| 946|/*********************************************************************** 947| 28. <<< [FileX_outPart] ファイルの一部を出力する >>> 948|【引数】 949| ・FILE* out; 出力先 950| ・FILE* in; 入力 951| ・int in_start; 入力開始位置 952| ・int in_over; 入力終了の次の位置 953|【補足】 954|・out と in は、バイナリファイルで開いてください。 955|************************************************************************/ 956|void FileX_outPart( FILE* out, FILE* in, int in_start, int in_over ) 957|{ 958| int leftSize = in_over - in_start; 959| int size; 960| char buf[2048]; 961| 962| #if ERRORS_DEBUG_FALSE 963| Errors_printf( "in_start = %d, in_over = %d", in_start, in_over ); 964| fprintf( out, "------------------------in_start = %d, in_over = %d\n", in_start, in_over ); 965| #endif 966| 967| ASSERT( in_start <= in_over ); 968| 969| fseek( in, in_start, SEEK_SET ); 970| 971| do { 972| size = ( leftSize < sizeof(buf) ) ? leftSize : sizeof(buf); 973| size = fread( buf, 1, size, in ); 974| if ( fwrite( buf, 1, size, out ) != (unsigned)size ) { 975| error2_0( FileX_Err_CannotWrite, "書きこみに失敗しました。" ); 976| } 977| leftSize -= size; 978| } while ( size == sizeof(buf) ); 979|} 980| 981|/************************************************************************* 982| 29. <<< [FileX_copyFolder] フォルダごとコピーする >>> 983|【引数】 984| ・bool bSub; サブフォルダもコピーする 985|【補足】 986|・コピー先のフォルダに含まれるファイル名が一致するときのみファイルを上書きします。 987|・書きこみに失敗したら、エラーになり、書き込み中だったコピー先のファイルは 988| 削除されます。すでに書きこんだファイルはそのまま残ります。 989|**************************************************************************/ 990|#ifdef USES_FILEFIND 991|#ifdef USES_NESTFIND 992|#if defined(USES_STDPLUS) && defined(USES_STRX) 993|#if defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE) 994|#if defined(WIN32) || defined(FOR_DOS32) 995|void FileX_copyFolder( const char* to_path, const char* from_path, 996| bool bSub ) 997|{ 998| NestFind find; 999| char from_path2[_MAX_PATH]; 1000| char to_path2[_MAX_PATH]; 1001| 1002| if ( FileX_isExist( to_path ) && ! FileX_isDir( to_path ) ) { 1003| error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。", 1004| to_path ); 1005| } 1006| FileX_mkdir2( to_path, 0 ); 1007| 1008|#if 0 1009| ASSERT( ! bSub ); 1010| FileFind_init( &find, from_path ); 1011| c_try { 1012| while ( FileFind_next( &find ) == 0 ) { 1013| if ( ! FileFind_isDir( &find ) ) { 1014| char* fname = FileFind_getFName( &find ); 1015| StrX_cpyAbsPath( from_path2, fname, _MAX_PATH, from_path ); 1016| StrX_cpyAbsPath( to_path2, fname, _MAX_PATH, to_path ); 1017| if ( FileX_isExist( from_path2 ) ) 1018| FileX_copy( to_path2, from_path2 ); 1019| } 1020| } 1021| } 1022| c_finally { 1023| FileFind_finish( &find ); 1024| } c_end_finally; 1025|#else 1026| NestFind_init( &find, from_path, false ); 1027| c_try { 1028| while ( NestFind_next( &find ) ) { 1029| char* fname = NestFind_getPath( &find ); 1030| StrX_cpyAbsPath( from_path2, fname, _MAX_PATH, from_path ); 1031| StrX_cpyAbsPath( to_path2, fname, _MAX_PATH, to_path ); 1032| if ( FileX_isExist( from_path2 ) ) 1033| FileX_copy( to_path2, from_path2 ); 1034| } 1035| } 1036| c_finally { 1037| NestFind_finish( &find ); 1038| } c_end_finally; 1039|#endif 1040|} 1041|#endif 1042|#endif 1043|#endif 1044|#endif 1045|#endif 1046| 1047|/************************************************************************* 1048| 30. <<< [FileX_removeFolder] フォルダごと削除する >>> 1049|【補足】 1050|・バックアップを取ってから実行してください。 1051|・システム領域は削除しないで下さい。 1052|・ごみ箱には格納されません。 1053|**************************************************************************/ 1054|#ifdef USES_NESTFIND 1055|#ifdef USES_WINX 1056|#ifdef USES_EXCEPT3 1057|void FileX_removeFolder( const char* path ) 1058|{ 1059| NestFind find; 1060| 1061| #ifdef NDEBUG 1062| #ifdef FOR_WIN32 1063| { 1064| char s[_MAX_PATH]; 1065| if ( stricmp( path, WinX_getWindowsPath() ) == 0 ) error(); 1066| GetSystemDirectory( s, sizeof(s) ); 1067| if ( stricmp( path, s ) == 0 ) error(); 1068| } 1069| #else 1070| #endif 1071| #endif 1072| 1073| if ( ! FileX_isExist( path ) ) return; 1074| 1075| NestFind_init( &find, path, true ); 1076| while ( NestFind_next( &find ) ) { 1077| if ( FileX_isDir( NestFind_getAbsPath( &find ) ) ) 1078| _rmdir( NestFind_getAbsPath( &find ) ); 1079| else { 1080| _chmod( NestFind_getAbsPath( &find ), _S_IREAD | _S_IWRITE ); 1081| remove( NestFind_getAbsPath( &find ) ); 1082| } 1083| } 1084| NestFind_finish( &find ); 1085| 1086| { 1087| char s[_MAX_PATH]; 1088| _getcwd( s, sizeof(s) ); 1089| if ( stricmp( s, path ) == 0 ) 1090| _chdir( ".." ); 1091| } 1092| if ( ! RemoveDirectory( path ) ) WinX_error(); 1093|} 1094|#endif 1095|#endif 1096|#endif 1097| 1098|/************************************************************************* 1099| 31. <<< [FileX_removeWild] ワイルドカードを指定してファイルを削除する >>> 1100|【補足】 1101|・wildPath の例:"c:\home\*.bak" 1102|・サブディレクトリは削除しません。 1103|・Visual C++ 専用です。 1104|・バックアップを取ってから実行してください。 1105|・システム領域は削除しないで下さい。 1106|・ごみ箱には格納されません。 1107|**************************************************************************/ 1108|void FileX_removeWild( const char* wildPath ) 1109|{ 1110| struct _finddata_t find; 1111| long handle; 1112| int done; 1113| int isdir; 1114| char folder[_MAX_PATH]; 1115| char path[_MAX_PATH]; 1116| 1117| StrX_cpyFolder( folder, wildPath ); 1118| handle = _findfirst( wildPath, &find ); 1119| done = (handle == -1); 1120| while ( !done ) { 1121| isdir = ( ( find.attrib & _A_SUBDIR ) != 0 ); 1122| if ( ! isdir ) { 1123| strcpy( path, folder ); strcat( path, "\\" ); 1124| strcat( path, find.name ); remove( path ); 1125| } 1126| done = _findnext( handle, &find ); 1127| } 1128| _findclose( handle ); 1129|} 1130| 1131| 1132| 1133|/************************************************************************* 1134| 32. <<< [FileX_setReadOnly] ファイルの読み込み専用属性を変更する >>> 1135|【引数】 1136| ・char* path; 読み込み専用属性を変更するファイルのパス 1137| ・bool bReadOnly; 設定する値(true=読み込み専用) 1138|**************************************************************************/ 1139|#if defined(USES_STDPLUS) && ( defined(FOR_WIN32) || defined(FOR_DOS32) ) 1140|void FileX_setReadOnly( const char* path, bool bReadOnly ) 1141|{ 1142| bool bSuccess; 1143| DWORD attr = GetFileAttributes( path ); 1144| if ( attr == 0xFFFFFFFF ) 1145| error(); /* ファイルが存在しないかも */ 1146| 1147| if ( bReadOnly ) attr |= FILE_ATTRIBUTE_READONLY; 1148| else attr &= ~FILE_ATTRIBUTE_READONLY; 1149| 1150| bSuccess = SetFileAttributes( path, attr ); 1151| if ( ! bSuccess ) error(); 1152|} 1153|#endif 1154| 1155|/************************************************************************* 1156| 33. <<< [FileX_cat] ファイルを連結する >>> 1157|**************************************************************************/ 1158|void FileX_cat( const char* to_path, const char* from_path ) 1159|{ 1160| FILE* to_file = FileX_open( to_path, "ab" ); 1161| FILE* from_file = FileX_open( from_path, "rb" ); 1162| size_t size; 1163| 1164| do { 1165| size = fread( FileX_buf, 1, sizeof(FileX_buf), from_file ); 1166| fwrite( FileX_buf, 1, size, to_file ); 1167| } while ( size == sizeof(FileX_buf) ); 1168| 1169| fclose( to_file ); 1170| fclose( from_file ); 1171|} 1172| 1173| 1174| 1175|/************************************************************************* 1176| 34. <<< [FileX_include] ファイルを埋めこむ >>> 1177|【引数】 1178|・int mode; to のモード{テキスト='t', バイナリ='b'} 1179|**************************************************************************/ 1180|void FileX_include( FILE* to, const char* from_path, int mode ) 1181|{ 1182| FILE* from_file; 1183| size_t size; 1184| char mode2[3]; 1185| 1186| strcpy( mode2, "rt" ); mode2[1] = mode; 1187| from_file = FileX_open( from_path, mode2 ); 1188| 1189| do { 1190| size = fread( FileX_buf, 1, sizeof(FileX_buf), from_file ); 1191| fwrite( FileX_buf, 1, size, to ); 1192| } while ( size == sizeof(FileX_buf) ); 1193| 1194| fclose( from_file ); 1195|} 1196| 1197| 1198| 1199| 1200|/************************************************************************* 1201| 35. <<< [FileX_putBase64] バイナリファイルを base64 に変換して出力する >>> 1202|【引数】 1203| ・FILE* f; 出力先(カレント・ファイルポインタへ出力) 1204| ・char* srcPath; 変換するバイナリファイルのパス 1205| ・char* retCh; base64 に格納する改行文字(Windows なら "\r\n") 1206|**************************************************************************/ 1207|void FileX_putBase64( FILE* f, const char* srcPath, const char* retCh ) 1208|{ 1209| FILE* f2 = FileX_open( srcPath, "rb" ); 1210| int binUnit = ( 32768 / StrX_unitOfBase64 ) * StrX_unitOfBase64; 1211| int textSize = StrX_getEncodedSizeOfBase64( binUnit, retCh ); 1212| char* bin = (char*)malloc( binUnit ); 1213| char* text = (char*)malloc( textSize ); 1214| int bin_size; 1215| 1216| while ( ! feof( f2 ) ) { 1217| bin_size = fread( bin, 1, binUnit, f2 ); 1218| StrX_encodeBase64( text, bin, bin_size, retCh ); 1219| fputs( text, f ); 1220| } 1221| 1222| free( text ); 1223| free( bin ); 1224| fclose( f2 ); 1225|} 1226| 1227| 1228| 1229|/************************************************************************* 1230| 36. <<< [FileX_scanBase64] base64 からバイナリファイルを出力する >>> 1231|【引数】 1232| ・FILE* f; 出力先(カレント・ファイルポインタへ出力) 1233| ・long pos; f のスキャンを開始するファイルポインタ(-1=カレントから) 1234| ・char* outPath; 出力するバイナリファイルのパス 1235|【補足】 1236|・base64 のデータの最後は、'\"' や '\'' など、base64 で使われない文字が 1237| あるところです。 1238|**************************************************************************/ 1239|void FileX_scanBase64( FILE* f, long pos, const char* outPath ) 1240|{ 1241| FILE* f2 = FileX_open( outPath, "wb" ); 1242| char text[80]; 1243| char bin[80]; 1244| int bin_size; 1245| char* p; 1246| 1247| if ( pos != -1 ) fseek( f, pos, SEEK_SET ); 1248| 1249| while ( ! feof( f ) ) { 1250| fgets( text, sizeof(text), f ); 1251| p = strchr( text, '\"' ); if ( p != NULL ) *p = '\0'; 1252| bin_size = StrX_decodeBase64( text, bin ); 1253| fwrite( bin, 1, bin_size, f2 ); 1254| if ( bin_size < StrX_unitOfBase64 ) break; 1255| } 1256| 1257| fclose( f2 ); 1258|} 1259| 1260| 1261| 1262|/************************************************************************* 1263| 37. <<< [FileX_mkdir2] フォルダを作成する >>> 1264|【引数】 1265| ・char* path; 実行中のフォルダからの相対パス、または絶対パス 1266| ・int bFile; path は、ファイルなら 1, フォルダなら 0 1267|【補足】 1268|・作成するフォルダを格納するフォルダが無ければ、再帰的に 1269| フォルダを作成します。 1270| 例:c:\a\b で a フォルダが無ければ、b フォルダだけでなく a フォルダも 1271| 作成します。 1272|・bFile を 1 にすると、path に指定したファイルを格納するフォルダを 1273| 作成します。 1274|**************************************************************************/ 1275|#ifdef USES_STRX 1276|#ifdef USES_BIGSTACK 1277|void FileX_mkdir2( const char* path, int bFile ) 1278|{ 1279| static char path2[_MAX_PATH]; 1280| static char* p; /* フォルダ区切り記号の位置(走査用) */ 1281| 1282| strcpy( path2, path ); 1283| StrX_getRunFullPath( path2, path2, _MAX_PATH - 1 ); 1284| if ( bFile ) StrX_cutFName( path2 ); 1285| StrX_cutLastOf2( path2, StrX_DirMark_char ); 1286| 1287| if ( path2[1] == ':' ) p = path2 + 2; 1288| else p = path2 - 1; 1289| 1290| while ( (p= StrX_strchr2( p + 1, StrX_DirMark_char )) != NULL ) { 1291| *p = '\0'; 1292| if ( ! FileX_isDir( path2 ) ) 1293| _mkdir( path2 ); /* フォルダを格納するフォルダを作成 */ 1294| *p = StrX_DirMark_char; 1295| } 1296| 1297| if ( bFile ) { 1298| strcpy( path2, path ); 1299| StrX_cutFName( path2 ); 1300| _mkdir( path2 ); 1301| } 1302| else { 1303| _mkdir( path ); 1304| } 1305|} 1306|#endif /* #ifdef USES_BIGSTACK */ 1307|#endif /* USES_STRX */ 1308| 1309| 1310| 1311|/************************************************************************* 1312| 38. <<< [FileX_backup] ファイルのバックアップをとる >>> 1313|【補足】 1314|・backup フォルダを作成して、そこに「移動」します。 1315|・backup フォルダには最新のバックアップと最古のバックアップが存在する 1316| ようになります。 1317|・バックアップ後の(最新の)ファイルパスは、FileX_toBackupPath 関数から 1318| 取得します。 1319|・path のファイルが存在しない場合、何もしません。 1320|**************************************************************************/ 1321|#if defined(USES_STDPLUS) && defined(USES_STRX) 1322|#if defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE) 1323|#if defined(WIN32) || defined(FOR_DOS32) 1324|void FileX_backup( const char* path ) 1325|{ 1326| int i; 1327| char s[_MAX_PATH]; 1328| #ifdef USES_TIMEDATE 1329| char s2[_MAX_PATH]; 1330| time_t t; 1331| time_t today; 1332| struct tm* tm; 1333| #endif 1334| 1335| if ( FileX_isExist( path ) ) { 1336| 1337| /* バックアップを格納するフォルダを作成する */ 1338| for ( i = 0; ; i++ ) { 1339| StrX_cpyFolder( s, path ); 1340| StrX_addFName( s, "backup" ); 1341| if ( i >= 1 ) sprintf( strchr( s, '\0' ), "%d", i ); 1342| if ( FileX_isDir( s ) ) break; 1343| if ( FileX_isExist( s ) ) continue; 1344| if ( _mkdir( s ) == -1 ) 1345| error2_1( FileX_Err_CannotMkdir, "フォルダ %s が作成できませんでした", s ); 1346| if ( FileX_isDir( s ) ) break; 1347| } 1348| 1349| /* ファイルをバックアップフォルダにコピーする(最新のバックアップ) */ 1350| StrX_addFName( s, StrX_refFName( path ) ); 1351| FileX_copy( s, path ); 1352| FileX_setReadOnly( s, false ); /* 上書きできるようにする */ 1353| 1354| /* ファイルをバックアップフォルダに移動する(本日最古のバックアップ) */ 1355| #ifdef USES_TIMEDATE 1356| strcpy( s2, s ); StrX_ins( StrX_refExt( s2 ) - 1, "#1" ); 1357| if ( ! FileX_isExist( s2 ) ) { 1358| FileX_copy( s2, s ); 1359| } 1360| else { 1361| FileX_getUpdate( s2, &t ); 1362| time( &today ); tm = localtime( &today ); 1363| TimeDate_set( &today, tm->tm_year + 1900, tm->tm_mon + 1, 1364| tm->tm_mday, 0,0,0 ); 1365| if ( difftime( t, today ) <= 0 ) 1366| FileX_copy( s2, s ); 1367| } 1368| #endif 1369| 1370| /* ファイルをバックアップフォルダに移動する(最古のバックアップ) */ 1371| strcpy( s2, s ); StrX_ins( StrX_refExt( s2 ) - 1, "#2" ); 1372| rename( path, s ); 1373| } 1374|} 1375|#endif 1376|#endif 1377|#endif 1378| 1379| 1380|/************************************************************************* 1381| 39. <<< [FileX_toBackupPath] ファイルのバックアップのパスに変更する >>> 1382|【引数】 1383| ・char* path; FileX_backup 関数に渡した引数 1384|【補足】 1385|・FileX_backup 関数で移動した先のパスを取得します。 1386|**************************************************************************/ 1387|#ifdef USES_STRX 1388|void FileX_toBackupPath( char* path ) 1389|{ 1390| StrX_cdFName( path, "backup" ); 1391|} 1392|#endif 1393| 1394| 1395| 1396|/************************************************************************* 1397| 40. <<< [FileX_write] 指定データをそのままファイルにする(バックアップ付き) >>> 1398|【引数】 1399| ・char* flag; "wb" または "wt" 1400|**************************************************************************/ 1401|#if defined(USES_STDPLUS) && defined(USES_STRX) 1402|#if defined(USES_BIGSTACK) && defined(USES_EXCEPT3) && defined(USES_TIMEDATE) 1403|#if defined(WIN32) || defined(FOR_DOS32) 1404|void FileX_write( const char* path, const char* flag, void* data, int size ) 1405|{ 1406| FILE* f; 1407| 1408| ASSERT( strchr( flag, 'r' ) == NULL ); 1409| 1410| FileX_backup( path ); 1411| FileX_mkdir2( path, true ); 1412| f = FileX_open( path, flag ); 1413| fwrite( data, 1, size, f ); 1414| fclose( f ); 1415|} 1416|#endif 1417|#endif 1418|#endif 1419| 1420| 1421|/************************************************************************* 1422| 41. <<< [FileX_read0] ファイルの内容をそのままデータにする >>> 1423|【引数】 1424| ・char* flag; "wb" または "wt" 1425| ・void* data; データを格納する領域の先頭アドレス 1426| ・int size; data のサイズ 1427| ・int 返り値; ファイルサイズ 1428|【補足】 1429|・データの末尾には '\0' が付きます。付ける必要が無ければ、標準関数の 1430| fread が使えます。 1431|・返り値(ファイルサイズ)が size より大きいときは、size - 1 まで 1432| 読み込みます。 1433|**************************************************************************/ 1434|#ifdef USES_STRX 1435|int FileX_read0( const char* path, const char* flag, void* data, int size ) 1436|{ 1437| FILE* f; 1438| int fsize; 1439| 1440| if ( strchr( flag, 'w' ) != NULL || strchr( flag, 'a' ) != NULL ) 1441| { error(); return 0; } 1442| 1443| fsize = FileX_getSize( path ); 1444| f = FileX_open( path, flag ); 1445| if ( fsize < size ) { 1446| fsize = fread( data, 1, fsize, f ); 1447| ((char*)data)[ fsize ] = '\0'; 1448| } 1449| else { 1450| size = fread( data, 1, size * 2, f ); 1451| ((char*)data)[ size ] = '\0'; 1452| } 1453| fclose( f ); 1454| 1455| return fsize; 1456|} 1457|#endif 1458| 1459|#if defined(FOR_WIN32) || defined(FOR_DOS32) 1460| 1461|/*--------------------------------------------------------------------*/ 1462|/* 42. <<<◆(FileX_UniRead) UNICODE ファイルを Shift-JIS として読み込むフィルタ >>> */ 1463|/*--------------------------------------------------------------------*/ 1464| 1465| 1466|/*********************************************************************** 1467| 43. <<< [FileX_UniRead_init] 読み込むファイルにフィルタをかける >>> 1468|【引数】 1469| ・char* path; 読み込むファイルのパス 1470| ・char* 返り値; 代わりに開くファイルパス、fopen 等に指定する 1471|【補足】 1472|・通常のファイル・オープンからクローズまでの外を FileX_UniRead_init と 1473| FileX_UniRead_finish で囲んでください。その際、通常のファイル・ 1474| オープンに使うファイルパスは、本関数の返り値を指定してください。 1475|・Shift JIS でフォーマットされた一時ファイルを作成して、そのパスを返します。 1476|・path は UNICODE ファイルでなくても構いません。そのとき、一時ファイルは 1477| 作成しません。 1478|************************************************************************/ 1479|char* FileX_UniRead_init( FileX_UniRead* m, const char* path ) 1480|{ 1481| ERRORS_INITCHK( m, 0 ); 1482| 1483| if ( FileX_isUnicodeFIle( path ) ) { 1484| FileX_getTmpPath( "unitmp", m->tmp_path ); 1485| FileX_copyUni2SJis( m->tmp_path, path ); 1486| return m->tmp_path; 1487| } 1488| else { 1489| m->tmp_path[0] = '\0'; 1490| return (char*)path; 1491| } 1492|} 1493| 1494| 1495| 1496| 1497|/*********************************************************************** 1498| 44. <<< [FileX_UniRead_finish] 読み込むファイルのフィルタを除く >>> 1499|************************************************************************/ 1500|void FileX_UniRead_finish( FileX_UniRead* m ) 1501|{ 1502| ERRORS_INITCHK( m, 1 ); 1503| 1504| if ( m->tmp_path[0] != '\0' ) 1505| remove( m->tmp_path ); 1506|} 1507| 1508| 1509| 1510|/*********************************************************************** 1511| 45. <<< [FileX_isUnicodeFIle] UNICODE のテキストファイルかどうかを返す >>> 1512|************************************************************************/ 1513|bool FileX_isUnicodeFIle( const char* path ) 1514|{ 1515| FILE* f; 1516| unsigned int size; 1517| unsigned short buf; 1518| 1519| f = FileX_open( path, "rb" ); 1520| 1521| size = fread( &buf, 1, 2, f ); 1522| fclose( f ); 1523| 1524| return ( size == 2 && buf == 0xFEFF ); 1525|} 1526| 1527| 1528|/*********************************************************************** 1529| 46. <<< [FileX_copyUni2SJis] UNICODE のファイルを Shift JIS に変換コピーする >>> 1530|************************************************************************/ 1531|void FileX_copyUni2SJis( const char* toSjisPath, const char* fromUniPath ) 1532|{ 1533| short* p; 1534| FILE* from_file; 1535| FILE* to_file; 1536| unsigned int size, size2; 1537| unsigned short buf[2048]; 1538| unsigned char buf2[4096]; 1539| 1540| /* ファイルを開く */ 1541| to_file = FileX_open( toSjisPath, "wb" ); 1542| if ( to_file == NULL ) Errors_errorStdlib(); 1543| from_file = FileX_open( fromUniPath, "rb" ); 1544| ASSERT( from_file != NULL ); 1545| 1546| /* UNICODE ファイルのヘッダをチェックする */ 1547| size = fread( buf, 1, 2, from_file ); 1548| if ( size < 2 || *buf != 0xFEFF ) { 1549| fclose( to_file ); fclose( from_file ); 1550| error2_0( FileX_Err_NotUnicodeFile, "UNICODE ファイルではありません" ); 1551| } 1552| 1553| /* ファイルの内容をコピーする */ 1554| do { 1555| size = fread( buf, 1, sizeof(buf) - 2, from_file ); 1556| p = (short*)( (char*)buf + size ); *p = (short)0; 1557| StrX_unicode2sjis( buf2, buf, sizeof(buf2) ); 1558| size2 = strlen( buf2 ); 1559| if ( fwrite( buf2, 1, size2, to_file ) != size2 ) { 1560| fclose( to_file ); fclose( from_file ); 1561| remove( toSjisPath ); 1562| FileX_bCopyFailed = true; 1563| error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。", 1564| toSjisPath ); 1565| } 1566| } while ( size == sizeof(buf) - 2 ); 1567| 1568| /* ファイルを閉じる */ 1569| fclose( to_file ); 1570| fclose( from_file ); 1571|} 1572| 1573| 1574|/*--------------------------------------------------------------------*/ 1575|/* 47. <<<◆(FileX_UniWrite) Shift-JIS 形式で書き込む UNICODE ファイルフィルタ >>> */ 1576|/*--------------------------------------------------------------------*/ 1577| 1578|/*********************************************************************** 1579| 48. <<< [FileX_UniWrite_init] 書き込むファイルにフィルタをかける >>> 1580|【引数】 1581| ・char* path; 書き込むファイルのパス 1582| ・char* 返り値; 代わりに開くファイルパス、fopen 等に指定する 1583|【補足】 1584|・通常のファイル・オープンからクローズまでの外を FileX_UniWrite_init と 1585| FileX_UniWrite_finish で囲んでください。その際、通常のファイル・ 1586| オープンに使うファイルパスは、本関数の返り値を指定してください。 1587|・FileX_UniWrite_finish で、作成した一時ファイルを UNICODE へ変換します。 1588|************************************************************************/ 1589|char* FileX_UniWrite_init( FileX_UniWrite* m, const char* path ) 1590|{ 1591| ERRORS_INITCHK( m, 0 ); 1592| 1593| FileX_getTmpPath( "unitmp", m->tmp_path ); 1594| strcpy( m->path, path ); 1595| 1596| return m->tmp_path; 1597|} 1598| 1599| 1600| 1601| 1602|/*********************************************************************** 1603| 49. <<< [FileX_UniWrite_finish] 書き込むファイルのフィルタを除く >>> 1604|************************************************************************/ 1605|void FileX_UniWrite_finish( FileX_UniWrite* m ) 1606|{ 1607| ERRORS_INITCHK( m, 1 ); 1608| 1609| FileX_copySJis2Uni( m->path, m->tmp_path ); 1610| remove( m->tmp_path ); 1611|} 1612| 1613| 1614| 1615|/*********************************************************************** 1616| 50. <<< [FileX_copySJis2Uni] Shift JIS のファイルを UNICODE に変換コピーする >>> 1617|************************************************************************/ 1618|void FileX_copySJis2Uni( const char* toUniPath, const char* fromSJisPath ) 1619|{ 1620| char* p; 1621| FILE* from_file; 1622| FILE* to_file; 1623| unsigned int size, size2; 1624| unsigned char buf[2048]; 1625| unsigned short buf2[2048]; 1626| 1627| /* ファイルを開く */ 1628| to_file = FileX_open( toUniPath, "wb" ); 1629| if ( to_file == NULL ) Errors_errorStdlib(); 1630| from_file = FileX_open( fromSJisPath, "rb" ); 1631| ASSERT( from_file != NULL ); 1632| 1633| /* UNICODE ファイルのヘッダを出力する */ 1634| *buf2 = 0xFEFF; 1635| if ( fwrite( buf2, 1, 2, to_file ) != 2 ) { 1636| fclose( to_file ); fclose( from_file ); 1637| remove( toUniPath ); 1638| FileX_bCopyFailed = true; 1639| error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。", 1640| toUniPath ); 1641| } 1642| 1643| /* ファイルの内容をコピーする */ 1644| do { 1645| size = fread( buf, 1, sizeof(buf) - 1, from_file ); 1646| if ( size == 0 ) break; 1647| 1648| p = buf + size - 1; *(p + 1) = '\0'; 1649| if ( StrX_isSJis1byte( buf, p ) ) *p = '\0'; 1650| StrX_sjis2unicode( buf2, buf, sizeof(buf2) ); 1651| size2 = wcslen( buf2 ) * 2; 1652| 1653| if ( fwrite( buf2, 1, size2, to_file ) != size2 ) { 1654| fclose( to_file ); fclose( from_file ); 1655| remove( toUniPath ); 1656| FileX_bCopyFailed = true; 1657| error2_1( FileX_Err_CannotWrite, "%s の書きこみに失敗しました。", 1658| toUniPath ); 1659| } 1660| 1661| if ( *p == '\0' ) fseek( from_file, -1, SEEK_CUR ); 1662| 1663| } while ( size == sizeof(buf) - 1 ); 1664| 1665| /* ファイルを閉じる */ 1666| fclose( to_file ); 1667| fclose( from_file ); 1668|} 1669| 1670|#endif 1671| 1672|/*--------------------------------------------------------------------*/ 1673|/* 51. <<<◆(FileX_CurDir) カレントフォルダ・スタック >>> */ 1674|/*--------------------------------------------------------------------*/ 1675| 1676| 1677| 1678|/************************************************************************* 1679| 52. <<< [FileX_CurDir_init] カレントフォルダをスタック的に変更する >>> 1680|【引数】 1681| ・char* path; 新しいカレントフォルダ、またはファイルのパス 1682|【補足】 1683|・この関数は、BigStack_start から BigStack_end の間に入れる必要があります。 1684|・m は、この関数を呼び出すたびに、新しくスタック変数として用意してください。 1685|・path にファイルを指定した場合、そのファイルを格納しているフォルダに 1686| カレントフォルダを変更します。 1687|・path は、相対パスでも絶対パスでも構いません。 1688|・相対パスで path に指定したファイルを開くときは、新しいカレントフォルダを 1689| 指定することに注意してください。 1690|【例】 1691| void func( char* fname ) 1692| { 1693| FileX_CurDir cur; 1694| 1695| BigStack_start(); 1696| FileX_CurDir_init( &cur, fname ); // fname のあるフォルダへ 1697| FileX_open( StrX_refFName( fname ), "rt" ); // カレントで開く 1698| ... 1699| FileX_CurDir_finish( &cur ); // 戻す 1700| BigStack_end(); 1701| } 1702|**************************************************************************/ 1703|#ifdef USES_STRX 1704|#ifdef USES_BIGSTACK 1705|void FileX_CurDir_init( FileX_CurDir* m, const char* path ) 1706|{ 1707| char* newDir; 1708| 1709| /* カレント・フォルダをとっておく */ 1710| m->curPath = BigStack_alloc( _MAX_PATH ); 1711| _getcwd( m->curPath, _MAX_PATH ); 1712| 1713| /* カレント・フォルダを変更する */ 1714| if ( FileX_isDir( path ) ) { 1715| _chdir( path ); 1716| } 1717| else { 1718| BigStack_start(); 1719| newDir = BigStack_alloc( _MAX_PATH ); 1720| strcpy( newDir, path ); 1721| StrX_cutFName( newDir ); 1722| _chdir( newDir ); 1723| BigStack_end(); 1724| } 1725|} 1726|#endif /* USES_BIGSTACK */ 1727|#endif /* USES_STRX */ 1728| 1729| 1730| 1731|/************************************************************************* 1732| 53. <<< [FileX_CurDir_finish] カレントフォルダを戻す >>> 1733|【補足】 1734|・この関数は、BigStack_start から BigStack_end の間に入れる必要があります。 1735|**************************************************************************/ 1736|#ifdef USES_BIGSTACK 1737|void FileX_CurDir_finish( FileX_CurDir* m ) 1738|{ 1739| _chdir( m->curPath ); 1740|} 1741|#endif /* USES_BIGSTACK */ 1742| 1743| 1744| 1745|/*---------------------------------------------------------------------*/ 1746|/* 54. <<<◆(FileX_FreeSpc) ディスクの空き容量 >>> */ 1747|/*---------------------------------------------------------------------*/ 1748| 1749|#ifdef FILEX_FREESIZE 1750| FileX_FreeSpc FileX_freeSpcSym; 1751|#endif 1752| 1753| 1754|/************************************************************************* 1755| 55. <<< [FileX_FreeSpc_init] 初期化する >>> 1756|【補足】 1757|・FileX_FreeSpc_scan してから、空き容量の変数が有効になります。 1758|**************************************************************************/ 1759|void FileX_FreeSpc_init( FileX_FreeSpc* m ) 1760|{ 1761| m->sectorsPerCluster = 0; 1762| m->bytesPerSector = 0; 1763| m->numberOfFreeClusters = 0; 1764| m->totalNumberOfClusters = 0; 1765|} 1766| 1767| 1768|/************************************************************************* 1769| 56. <<< [FileX_FreeSpc_scan] 空き容量をディスクから取得する >>> 1770|【引数】 1771| ・char* root_path; ルートのパス(例:"c:\\") 1772|【補足】 1773|・取得したサイズは、FileX_FreeSpc_getFreeSize 関数などから取得します。 1774|・FILEX_FREESIZE を #define すると、空き容量をシミュレートできます。 1775| FileX_freeSpcSym グローバル変数(FileX_FreeSpc型)のメンバ変数に 1776| 設定してください。 1777|**************************************************************************/ 1778|#ifdef WIN32 1779|void FileX_FreeSpc_scan( FileX_FreeSpc* m, const char* root_path ) 1780|{ 1781| #ifdef FILEX_FREESIZE 1782| *m = FileX_freeSpcSym; 1783| #else 1784| if ( ! GetDiskFreeSpace( root_path, &m->sectorsPerCluster, 1785| &m->bytesPerSector, &m->numberOfFreeClusters, 1786| &m->totalNumberOfClusters ) ) { 1787| m->sectorsPerCluster = 0; 1788| m->bytesPerSector = 0; 1789| m->numberOfFreeClusters = 0; 1790| m->totalNumberOfClusters = 0; 1791| } 1792| #endif 1793|} 1794|#endif 1795| 1796|/************************************************************************* 1797| 57. <<< [FileX_FreeSpc_getFreeSize] 空き容量を計算する >>> 1798|【補足】 1799|・書き込みできるかどうか判断するときは、上書きすることを考慮に入れてください。 1800| → FileX_FreeSpc_getUseFileSize 関数 1801|・1KB = 1024byte, 1MB = 1024KB 1802|**************************************************************************/ 1803|int FileX_FreeSpc_getFreeSize( FileX_FreeSpc* m ) 1804|{ 1805| return m->sectorsPerCluster * 1806| m->bytesPerSector * m->numberOfFreeClusters; 1807|} 1808| 1809| 1810|/************************************************************************* 1811| 58. <<< [FileX_FreeSpc_getTotalSize] 総容量を計算する >>> 1812|【補足】 1813|・1KB = 1024byte, 1MB = 1024KB, 1GB = 1024MB 1814|**************************************************************************/ 1815|int FileX_FreeSpc_getTotalSize( FileX_FreeSpc* m ) 1816|{ 1817| return m->sectorsPerCluster * 1818| m->bytesPerSector * m->totalNumberOfClusters; 1819|} 1820| 1821| 1822|/************************************************************************* 1823| 59. <<< [FileX_FreeSpc_getUseFileSize] ファイルの使用サイズを返す >>> 1824|【引数】 1825| ・FileX_FreeSpc* m; ドライブの空き容量 1826| ・char* path; ファイルパス 1827| ・int 返り値; ファイルの使用サイズ 1828|【補足】 1829|・m を初期化してから使用してください。 1830|・ファイルシステムでは、クラスタ単位で領域を扱っているため、実際の 1831| ファイルサイズより大きめの領域を使用しています。その領域のサイズを 1832| 返します。 1833|・指定したファイルが存在しない場合は、0 を返します。 1834|・m と path のドライブが異なる場合、path のファイルを m の 1835| ドライブに格納したときの使用サイズを返します。 1836|**************************************************************************/ 1837|#ifdef USES_EXCEPT3 1838|int FileX_FreeSpc_getUseFileSize( FileX_FreeSpc* m, const char* path ) 1839|{ 1840| int size; 1841| int nCluster; 1842| int bytesPerCluster = m->sectorsPerCluster * m->bytesPerSector; 1843| 1844| if ( ! FileX_isExist( path ) ) return 0; 1845| size = FileX_getSize( path ); 1846| nCluster = FileX_FreeSpc_culcNCluster( m, size ); 1847| return nCluster * bytesPerCluster; 1848|} 1849|#endif 1850| 1851| 1852|/************************************************************************* 1853| 60. <<< [FileX_FreeSpc_culcNCluster] 指定サイズが使うクラスタ数を返す >>> 1854|【引数】 1855| ・int size; ファイルのサイズ(バイト) 1856|**************************************************************************/ 1857|int FileX_FreeSpc_culcNCluster( FileX_FreeSpc* m, int size ) 1858|{ 1859| int bytesPerCluster = m->sectorsPerCluster * m->bytesPerSector; 1860| 1861| return ( size + bytesPerCluster - 1 ) / bytesPerCluster; 1862|} 1863| 1864| 1865|