Subversion Repositories spk

Rev

Rev 33 | Rev 51 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
#include "File_IO.h"
2
 
3
#ifdef _WIN32
4
#include <windows.h>
5
#endif
6
 
7
#include <locale>
8
 
9
#include "DirIO.h"
10
#include "File.h"
11
 
12
CFileIO::CFileIO ()
13
{
14
	m_bOpened = false;
15
	m_lSize = 0;
16
	m_bBinary = true;
17
	m_fIdOld = NULL;
18
}
19
 
20
CFileIO::CFileIO(CyString filename)
21
{
22
	m_bOpened = false;
23
	m_lSize = 0;
24
	m_bBinary = true;
25
	m_fIdOld = NULL;
26
 
27
	Open ( filename, true );
28
}
29
 
30
CFileIO::CFileIO(C_File *file)
31
{
32
	m_bOpened = false;
33
	m_lSize = 0;
34
	m_bBinary = true;
35
	m_fIdOld = NULL;
36
 
37
	Open ( file->GetFilePointer(), true );
38
}
39
 
40
CFileIO::~CFileIO()
41
{
42
	if ( m_bOpened )
43
	{
44
		if ( m_fIdOld )
45
			fclose(m_fIdOld);
46
		else
47
			m_fId.close();
48
	}
49
}
50
 
51
bool CFileIO::Open ( CyString filename, bool binary )
52
{
53
	m_bBinary = binary;
54
	m_sFilename = filename;
55
	m_sFilename = m_sFilename.FindReplace ( "\\", "/" );
56
 
57
	if ( m_sFilename.IsIn('/') )
58
	{
59
		m_sDirIO.SetDir(m_sFilename.GetToken ( "/", 1, m_sFilename.NumToken ( "/" ) - 1 ));
60
		m_sFile = m_sFilename.GetToken ( "/", m_sFilename.NumToken ( "/" ) );
61
	}
62
	else
63
		m_sFile = filename;
64
 
65
	ReadFileSize();
66
	return true;
67
}
68
bool CFileIO::WritePartFile ( size_t *offsets, size_t numOffset )
69
{
70
	if ( NoFile() )
71
		return false;
72
 
73
	FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb+" : "r+" );
74
	if ( !id )
75
		return false;
76
 
77
	// first find file size
78
	fseek ( id, 0, SEEK_END );
79
	size_t fullsize = ftell ( id ), size = fullsize;
80
	fseek ( id, 0, SEEK_SET );
81
 
82
	FILE *writeId = fopen ( "temp.tmp", (m_bBinary) ? "wb" : "w" );
83
	if ( !writeId )
84
	{
85
		fclose ( id );
86
		return false;
87
	}
88
 
89
	size_t off = 0;
90
 
91
	size_t startPos = 0;
92
	size_t remainingSize = fullsize;
93
	while ( off < numOffset )
94
	{
95
		startPos = ftell(id);
96
		size_t offset = offsets[off++];
97
		size_t size = offset - startPos;
98
		char *data = new char[size];
99
		fread ( data, sizeof(unsigned char), size, id );
100
		fwrite ( data, sizeof(unsigned char), size, writeId );
101
		delete data;
102
		size_t datasize = offsets[off++];
103
		fseek ( id, datasize, SEEK_CUR );
104
		remainingSize = fullsize - offset - datasize;
105
	}
106
 
107
	if ( remainingSize )
108
	{
109
		char data[1000000];
110
		size_t amountLeft = 1000000;
111
		while ( remainingSize )
112
		{
113
			if ( amountLeft > remainingSize )
114
				amountLeft = remainingSize;
115
			fread ( data, sizeof(unsigned char), amountLeft, id );
116
			fwrite ( data, sizeof(unsigned char), amountLeft, writeId );
117
 
118
			remainingSize -= amountLeft;
119
			amountLeft = 1000000;
120
		}
121
	}
122
 
123
	fclose ( writeId );
124
	fclose ( id );
125
 
126
	// now copy to original file
127
	remove ( m_sFilename.c_str() );
128
	rename ( "temp.tmp", m_sFilename.c_str() );
129
 
130
	return true;
131
}
132
 
133
 
134
void CFileIO::SetDir ( CyString dir )
135
{
136
	if ( m_sFile.Empty() )
137
		m_sDirIO.SetDir(dir);
138
	else
139
		Open ( dir + "/" + m_sFile, m_bBinary );
140
}
141
 
142
void CFileIO::ReadFileSize ()
143
{
144
	FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb" : "r" );
145
	if ( !id )
146
	{
147
		m_lSize = 0;
148
		return;
149
	}
150
	fseek ( id, 0, SEEK_END );
151
	m_lSize = ftell ( id );
152
	fseek ( id, 0, SEEK_SET );
153
	fclose ( id );
154
}
155
 
156
bool CFileIO::WipeFile()
157
{
158
	if ( NoFile() )
159
		return false;
160
 
161
	FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb+" : "r+" );
162
	if ( !id )
163
		return false;
164
	fclose(id);
165
 
166
	return true;
167
}
168
int CFileIO::TruncateFile ( size_t offset, size_t datasize )
169
{
170
	if ( NoFile() )
171
		return FILEERR_NOFILE;
172
 
173
	FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb+" : "r+" );
174
	if ( !id )
175
		return FILEERR_NOOPEN;
176
 
177
	// first find file size
178
	fseek ( id, 0, SEEK_END );
179
	size_t fullsize = ftell ( id ), size = fullsize;
180
	fseek ( id, 0, SEEK_SET );
181
 
182
	if ( (offset + datasize) > fullsize )
183
		return FILEERR_TOSMALL;
184
//	char data[500000];
185
 
186
#ifdef _WIN32
187
	FILE *writeId = fopen ( "temp.tmp", (m_bBinary) ? "wb" : "w" );
188
	if ( !writeId )
189
	{
190
		fclose ( id );
191
		return FILEERR_NOWRITE;
192
	}
193
 
194
	char *data = new char[offset];
195
	fread ( data, sizeof(unsigned char), offset, id );
196
	fwrite ( data, sizeof(unsigned char), offset, writeId );
197
	delete data;
198
 
199
	// next fseek after and write
200
	fseek ( id, datasize, SEEK_CUR );
201
	size = fullsize - offset - datasize;
42 cycrow 202
	if ( size > 0 ) {
203
		data = new char[size];
204
		fread ( data, sizeof(unsigned char), size, id );
205
		fwrite ( data, sizeof(unsigned char), size, writeId );
206
		delete data;
207
	}
1 cycrow 208
 
209
	fclose ( writeId );
210
	fclose ( id );
211
 
212
	// now copy to original file
213
	remove ( m_sFilename.c_str() );
214
	rename ( "temp.tmp", m_sFilename.c_str() );
215
 
216
#else
217
	// move to beginning of file data to remove
218
	fseek ( id, offset, SEEK_SET );
219
 
220
	size_t writepos = offset;
221
	size_t readpos = offset + datasize;
222
 
223
	size -= readpos;
224
 
225
	while ( size > 0 )
226
	{
227
		int read = 500000;
228
		if ( read > size )
229
			read = size;
230
 
231
		// read data
232
		fseek ( id, readpos, SEEK_SET );
233
		fread ( data, sizeof(unsigned char), read, id );
234
		size -= read;
235
		readpos += read;
236
 
237
		// now seek back and write
238
		fseek ( id, writepos, SEEK_SET );
239
		fwrite ( data, sizeof(unsigned char), read, id );
240
		writepos += read;
241
 
242
	}
243
 
244
	truncate ( m_sFilename.c_str(), fullsize - datasize );
245
	fclose ( id );
246
#endif
247
 
248
	return FILEERR_NONE;
249
}
250
 
251
char *CFileIO::ReadToData ( size_t *size )
252
{
253
	*size = 0;
254
 
255
	if ( NoFile() )
256
		return NULL;
257
 
258
	if ( !m_lSize )
259
		ReadFileSize();
260
 
261
	if ( !m_lSize )
262
		return NULL;
263
 
264
	FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb" : "r" );
265
	if ( !id )
266
		return NULL;
267
 
268
	char *data = new char[m_lSize];
269
 
270
	fread ( data, sizeof(char), m_lSize, id );
271
	if ( ferror (id) )
272
	{
273
		fclose ( id );
274
		return NULL;
275
	}
276
 
277
	*size = m_lSize;
278
	fclose ( id );
279
 
280
	return data;
281
}
282
 
283
bool CFileIO::WriteData ( const char *data, size_t size )
284
{
285
	if ( NoFile() )
286
		return false;
287
 
288
	FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "wb" : "w" );
289
	if ( !id )
290
		return false;
291
 
292
	fwrite ( data, size, sizeof(char), id );
293
	fclose ( id );
294
 
295
	ReadFileSize();
296
 
297
	return true;
298
}
299
 
300
bool CFileIO::WriteString ( CyString data )
301
{
302
	return WriteData ( data.c_str(), data.Length() );
303
}
304
 
305
bool CFileIO::Exists ()
306
{
307
	FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb" : "r" );
308
	if ( !id )
309
		return false;
310
 
311
	fclose ( id );
312
	return true;
313
}
314
 
315
bool CFileIO::StartReadOld()
316
{
317
	if ( !m_sFilename.Empty() )
318
	{
319
		if ( m_bOpened )
320
			StopRead();
321
 
322
		m_fIdOld = fopen(m_sFilename.c_str(), "rb");
323
		if ( !m_fIdOld )
324
			return false;
325
		m_bOpened = true;
326
		return true;
327
	}
328
	return false;
329
}
330
 
331
bool CFileIO::StartRead()
332
{
333
	if ( !m_sFilename.Empty() )
334
	{
335
		if ( m_bOpened )
336
			StopRead();
337
 
338
		m_fId.open(m_sFilename.c_str(), std::ios_base::in);
339
		if ( m_fId.is_open() )
340
		{
341
			m_bOpened = true;
342
			return true;
343
		}
344
	}
345
	return false;
346
}
347
 
348
std::vector<CyString> *CFileIO::ReadLines()
349
{
350
	if ( m_sFilename.Empty() )
351
		return 0;
352
 
353
	std::vector<CyString> *file = new std::vector<CyString>;
354
	std::string line;
355
	file->clear();
356
	std::ifstream infile (m_sFilename.c_str(), std::ios_base::in);
357
	while (getline(infile, line, '\n'))
358
	{
359
		CyString l = line;
360
		l.RemoveChar((char)0);
361
		file->push_back(l);
362
	}
363
 
364
	infile.close();
365
 
366
	return file;
367
}
368
 
369
CyStringList *CFileIO::ReadLinesStr()
370
{
371
	if ( m_sFilename.Empty() )
372
		return 0;
373
 
374
	CyStringList *file = new CyStringList;
375
	std::string line;
376
	std::ifstream infile (m_sFilename.c_str(), std::ios_base::in);
377
	while (getline(infile, line, '\n'))
378
	{
379
		CyString l = line;
380
		l.RemoveChar((char)0);
381
		file->PushBack(l);
382
	}
383
 
384
	infile.close();
385
 
386
	return file;
387
}
388
 
389
void CFileIO::StopRead()
390
{
391
	if ( m_bOpened )
392
	{
393
		if ( m_fIdOld )
394
			fclose(m_fIdOld);
395
		else
396
			m_fId.close();
397
	}
398
	m_fIdOld = NULL;
399
	m_bOpened = false;
400
}
401
 
402
bool CFileIO::IsOpened()
403
{
404
	if ( !m_bOpened )
405
		return false;
406
	if ( m_fIdOld )
407
		return true;
408
	if ( m_fId.is_open() )
409
		return true;
410
	return false;
411
}
412
 
413
CyString CFileIO::ReadToEndLine(bool autoclose)
414
{
415
	if ( !this->IsOpened() )
416
	{
417
		if ( !StartRead() )
418
			return "";
419
	}
420
 
421
	int pos = 0;
422
	char sLine[10000];
423
	char cur = 0;
424
 
425
	if ( m_fIdOld )
426
	{
427
		while ( !feof(m_fIdOld) )
428
		{
429
			cur = fgetc(m_fIdOld);
430
			if ( cur == '\n' || cur == '\r' )
431
				break;
432
			sLine[pos++] = cur;
433
		}
434
	}
435
	else
436
	{
437
		std::string line;
438
		if ( getline(m_fId, line, '\n') )
439
			return CyString(line);
440
	}
441
 
442
	sLine[pos] = 0;
443
	if ( pos )
444
		return CyString(sLine);
445
 
446
	if ( autoclose )
447
		StopRead();
448
	return "";
449
}
450
 
451
bool CFileIO::AtEnd()
452
{
453
	if ( !m_bOpened )
454
		return true;
455
 
456
	if ( m_fIdOld )
457
	{
458
		if ( feof(m_fIdOld) )
459
			return true;
460
	}
461
	else
462
	{
463
		if ( m_fId.eof() )
464
			return true;
465
	}
466
 
467
	return false;
468
}
469
 
470
bool CFileIO::AppendFile ( CyString filename )
471
{
472
	FILE *id = fopen ( filename.c_str(), (m_bBinary) ? "rb" : "r" );
473
	if ( !id )
474
		return false;
475
 
476
	FILE *aid = fopen ( m_sFilename.c_str(), (m_bBinary) ? "ab" : "a" );
477
	if ( !aid )
478
	{
479
		return false;
480
		fclose ( id );
481
	}
482
 
483
	// move to the end of the file
484
	fseek ( aid, 0, SEEK_END );
485
 
486
	// get size of file
487
	fseek ( id, 0, SEEK_END );
488
	size_t size = ftell ( id );
489
	fseek ( id, 0, SEEK_SET );
490
 
491
	char data[500000];
492
	while ( size > 0 )
493
	{
494
		size_t read = 500000;
495
		if ( read > size )
496
			read = size;
497
 
498
		size -= read;
499
 
500
		fread ( data, sizeof(char), read, id );
501
		fwrite ( data, sizeof(char), read, aid );
502
	}
503
 
504
	fclose ( aid );
505
	fclose ( id );
506
	return true;
507
}
508
 
509
 
510
bool CFileIO::AppendData ( const char *d, size_t size )
511
{
512
	FILE *aid = fopen ( m_sFilename.c_str(), (m_bBinary) ? "ab" : "a" );
513
	if ( !aid )
514
		return false;
515
 
516
	// move to the end of the file
517
	fseek ( aid, 0, SEEK_END );
518
 
519
	char *pos = (char *)d;
520
	while ( size > 0 )
521
	{
522
		size_t read = 500000;
523
		if ( read > size )
524
			read = size;
525
 
526
		size -= read;
527
 
528
		fwrite ( pos, sizeof(char), read, aid );
529
		pos += read;
530
	}
531
 
532
	fclose ( aid );
533
	return true;
534
}
535
 
536
bool CFileIO::AppendDataToPos ( const char *d, size_t size, size_t start )
537
{
538
	FILE *aid = fopen ( m_sFilename.c_str(), (m_bBinary) ? "ab" : "a" );
539
	if ( !aid )
540
		return false;
541
 
542
	// move to the end of the file
543
	fseek ( aid, 0, SEEK_END );
544
	size_t end = ftell(aid);
545
	if ( start > end )
546
	{
547
		fclose ( aid);
548
		return false;
549
	}
550
 
42 cycrow 551
	if ( start == end ) {
552
		fseek(aid, 0, SEEK_END);
553
	}
554
	else {
555
		fseek ( aid, start, SEEK_SET );
556
	}
1 cycrow 557
 
558
	char *pos = (char *)d;
559
	while ( size > 0 )
560
	{
561
		size_t read = 500000;
562
		if ( read > size )
563
			read = size;
564
 
565
		size -= read;
566
 
567
		fwrite ( pos, sizeof(char), read, aid );
568
		pos += read;
569
	}
570
 
571
	fclose ( aid );
572
	return true;
573
}
574
 
575
CyString CFileIO::GetBaseName()
576
{
577
	return m_sFile.GetTokenRev(".", 1, -1);
578
}
579
CyString CFileIO::GetFileExtension ()
580
{
581
	if ( m_sFilename.Empty() )
582
		return NullString;
583
 
584
	CyString ext = m_sFilename.GetToken ( ".", m_sFilename.NumToken ( "." ) );
585
	return ext;
586
}
587
 
588
CyString CFileIO::ChangeFileExtension ( CyString ext )
589
{
590
	if ( m_sFilename.Empty() )
591
		return NullString;
592
 
593
	CyString noext = m_sFilename.GetToken ( ".", 1, m_sFilename.NumToken ( "." ) - 1 );
594
	return noext + "." + ext;
595
}
596
 
597
bool CFileIO::Remove()
598
{
599
	if ( !Exists() )
600
		return false;
601
 
602
	if ( remove(m_sFilename.c_str()) == 0 )
603
		return true;
604
 
605
	return false;
606
}
607
 
608
bool CFileIO::WriteFileUTF(std::vector<CyString> *lines)
609
{
610
	if ( !lines || m_sFilename.Empty() )
611
		return false;
612
 
613
	// we need to create the directory
614
	if ( !m_sDirIO.Exists() )
615
	{
616
		if ( !m_sDirIO.Create() )
617
			return false;
618
	}
619
 
620
#ifdef _WIN32
621
	TCHAR buf[5000];
622
	wsprintf(buf, L"%hs", m_sFilename.c_str());
623
	FILE *id = _wfopen(buf, L"wt+,ccs=UTF-8");
624
	if ( !id )
625
		return false;
626
 
627
	// write the rest
628
	for ( int i = 0; i < (int)lines->size(); i++ )
629
	{
630
		CyString l = lines->at(i);
631
		if ( l.IsIn('\n') )
632
		{
633
			int max;
634
			CyString *strs = l.SplitToken("\n", &max);
635
			if ( strs && max )
636
			{
637
				for ( int i = 0; i < max; i++ )
638
				{
639
					CyString line = strs[i];
640
					line += "\n";
641
					int size = wsprintf(buf, L"%hs", line.c_str());
642
					fwrite(buf, sizeof(TCHAR), wcslen(buf), id);
643
				}
644
 
645
				CLEANSPLIT(strs, max);
646
			}
647
		}
648
		else
649
		{
650
			l += "\n";
651
			int size = wsprintf(buf, L"%hs", l.c_str());
652
			fwrite(buf, sizeof(TCHAR), wcslen(buf), id);
653
		}
654
	}
655
 
656
	fclose(id);
657
 
658
	return true;
659
#else
660
    //TODO: write utf8 file writing function
661
    return false;
662
#endif
663
}
664
 
665
bool CFileIO::WriteFile(std::vector<CyString> *lines)
666
{
667
	if ( !lines || m_sFilename.Empty() )
668
		return false;
669
 
670
	// we need to create the directory
671
	if ( !m_sDirIO.Exists() )
672
	{
673
		if ( !m_sDirIO.Create() )
674
			return false;
675
	}
676
 
677
 
678
	std::ofstream out(m_sFilename.c_str());
679
	if ( !out )
680
		return false;
681
 
682
	for ( int i = 0; i < (int)lines->size(); i++ )
683
	{
684
		CyString l = lines->at(i);
685
		out << l.c_str() << std::endl;
686
	}
687
 
688
	out.close();
689
 
690
	return true;
691
}
692
 
693
bool CFileIO::WriteFile(CyStringList *lines)
694
{
695
	if ( !lines || m_sFilename.Empty() )
696
		return false;
697
 
698
	// we need to create the directory
699
	if ( !m_sDirIO.Exists() )
700
	{
701
		if ( !m_sDirIO.Create() )
702
			return false;
703
	}
704
 
705
	std::ofstream out(m_sFilename.c_str());
706
	if ( !out )
707
		return false;
708
 
709
	/*
710
	if ( utf )
711
	{
712
		unsigned char smarker[4];
713
		smarker[0] = 0xEF;
714
		smarker[1] = 0xBB;
715
		smarker[2] = 0xBF;
716
		smarker[3] = 0x00;
717
 
718
		out << smarker;
719
	}
720
*/
721
	for ( int i = 0; i < (int)lines->Count(); i++ )
722
	{
723
		CyString l = lines->StringAt(i);
724
		out << l.c_str() << std::endl;
725
	}
726
 
727
	out.close();
728
 
729
	return true;
730
}
731
 
732
bool CFileIO::Rename(CyString toFile)
733
{
734
	if ( rename(m_sFilename.c_str(), toFile.c_str()) == 0 )
735
		return true;
736
	return false;
737
}
738
 
739
CyString CFileIO::GetWindowsFilename()
740
{
741
	CyString returnString = m_sFilename;
742
	returnString = returnString.FindReplace("/", "\\");
743
	return returnString;
744
}
745
 
746
void CFileIO::SetCreationTime(time_t time)
747
{
748
#ifdef _WIN32
749
	// Note that LONGLONG is a 64-bit value
750
    LONGLONG ll;
751
 
752
	FILETIME ft;
753
    ll = Int32x32To64(time, 10000000) + 116444736000000000;
754
    ft.dwLowDateTime = (DWORD)ll;
755
    ft.dwHighDateTime = ll >> 32;
756
 
757
	HANDLE filename = CreateFile((LPCWSTR)GetWindowsFilename().c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
758
	// Set the file time on the file
759
	SetFileTime(filename,(LPFILETIME) NULL,(LPFILETIME) NULL,&ft);
760
	// Close our handle.
761
	CloseHandle(filename);
762
#endif
763
}
764
 
765
time_t CFileIO::GetCreationTime()
766
{
767
#ifdef _WIN32
768
	WIN32_FILE_ATTRIBUTE_DATA wfad;
769
	GetFileAttributesEx((LPCWSTR)GetWindowsFilename().c_str(), GetFileExInfoStandard, &wfad);
770
 
771
	LARGE_INTEGER date, adjust;
772
	date.HighPart = wfad.ftCreationTime.dwHighDateTime;
773
	date.LowPart = wfad.ftCreationTime.dwLowDateTime;
774
 
775
	// 100-nanoseconds = milliseconds * 10000
776
	adjust.QuadPart = 11644473600000 * 10000;
777
 
778
	// removes the diff between 1970 and 1601
779
	date.QuadPart -= adjust.QuadPart;
780
 
781
	// converts back from 100-nanoseconds to seconds
782
	return (time_t)(date.QuadPart / 10000000);
783
#else
784
	struct stat fileStat;
785
	if ( !stat(GetWindowsFilename().c_str(), &fileStat) )
786
		return (time_t)fileStat.st_atime;
787
#endif
788
	return 0;
789
}
790
/**
791
 * Copys the contents of a file to another
792
 *
793
 * Reads and writes the files in block
794
 */
795
bool CFileIO::Copy(CyString toFile, bool keepTime)
796
{
797
	//open both files
798
	FILE *id = fopen(GetWindowsFilename().c_str(), "rb");
799
	if ( !id )
800
		return false;
801
	FILE *toID = fopen(toFile.c_str(), "wb");
802
	if ( !toID )
803
	{
804
		fclose(id);
805
		return false;
806
	}
807
 
808
	time_t time = GetCreationTime();
809
 
810
	// get length of file
811
	fseek(id, 0, SEEK_END);
812
	size_t remainingLen = ftell(id);
813
	fseek(id, 0, SEEK_SET);
814
 
815
	if ( remainingLen <= 0 )
816
	{
817
		fclose(id);
818
		fclose(toID);
819
		return false;
820
	}
821
 
822
 
823
	// read then write a block
824
	char block[100000];
825
	while ( remainingLen )
826
	{
827
		size_t amt = 100000;
828
		if ( amt > remainingLen )
829
			amt = remainingLen;
830
 
831
		fread(block, amt, sizeof(char), id);
832
		fwrite(block, amt, sizeof(char), toID);
833
 
834
		remainingLen -= amt;
835
	}
836
 
837
	fclose(id);
838
	fclose(toID);
839
 
840
	if ( keepTime )
841
		CFileIO(toFile.c_str()).SetCreationTime(time);
842
 
843
 
844
	return true;
845
}