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