Rev 1 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "File_IO.h"#ifdef _WIN32#include <windows.h>#endif#include <locale>#include "DirIO.h"#include "File.h"CFileIO::CFileIO (){m_bOpened = false;m_lSize = 0;m_bBinary = true;m_fIdOld = NULL;}CFileIO::CFileIO(CyString filename){m_bOpened = false;m_lSize = 0;m_bBinary = true;m_fIdOld = NULL;Open ( filename, true );}CFileIO::CFileIO(C_File *file){m_bOpened = false;m_lSize = 0;m_bBinary = true;m_fIdOld = NULL;Open ( file->GetFilePointer(), true );}CFileIO::~CFileIO(){if ( m_bOpened ){if ( m_fIdOld )fclose(m_fIdOld);elsem_fId.close();}}bool CFileIO::Open ( CyString filename, bool binary ){m_bBinary = binary;m_sFilename = filename;m_sFilename = m_sFilename.FindReplace ( "\\", "/" );if ( m_sFilename.IsIn('/') ){m_sDirIO.SetDir(m_sFilename.GetToken ( "/", 1, m_sFilename.NumToken ( "/" ) - 1 ));m_sFile = m_sFilename.GetToken ( "/", m_sFilename.NumToken ( "/" ) );}elsem_sFile = filename;ReadFileSize();return true;}bool CFileIO::WritePartFile ( size_t *offsets, size_t numOffset ){if ( NoFile() )return false;FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb+" : "r+" );if ( !id )return false;// first find file sizefseek ( id, 0, SEEK_END );size_t fullsize = ftell ( id ), size = fullsize;fseek ( id, 0, SEEK_SET );FILE *writeId = fopen ( "temp.tmp", (m_bBinary) ? "wb" : "w" );if ( !writeId ){fclose ( id );return false;}size_t off = 0;size_t startPos = 0;size_t remainingSize = fullsize;while ( off < numOffset ){startPos = ftell(id);size_t offset = offsets[off++];size_t size = offset - startPos;char *data = new char[size];fread ( data, sizeof(unsigned char), size, id );fwrite ( data, sizeof(unsigned char), size, writeId );delete data;size_t datasize = offsets[off++];fseek ( id, datasize, SEEK_CUR );remainingSize = fullsize - offset - datasize;}if ( remainingSize ){char data[1000000];size_t amountLeft = 1000000;while ( remainingSize ){if ( amountLeft > remainingSize )amountLeft = remainingSize;fread ( data, sizeof(unsigned char), amountLeft, id );fwrite ( data, sizeof(unsigned char), amountLeft, writeId );remainingSize -= amountLeft;amountLeft = 1000000;}}fclose ( writeId );fclose ( id );// now copy to original fileremove ( m_sFilename.c_str() );rename ( "temp.tmp", m_sFilename.c_str() );return true;}void CFileIO::SetDir ( CyString dir ){if ( m_sFile.Empty() )m_sDirIO.SetDir(dir);elseOpen ( dir + "/" + m_sFile, m_bBinary );}void CFileIO::ReadFileSize (){FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb" : "r" );if ( !id ){m_lSize = 0;return;}fseek ( id, 0, SEEK_END );m_lSize = ftell ( id );fseek ( id, 0, SEEK_SET );fclose ( id );}bool CFileIO::WipeFile(){if ( NoFile() )return false;FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb+" : "r+" );if ( !id )return false;fclose(id);return true;}int CFileIO::TruncateFile ( size_t offset, size_t datasize ){if ( NoFile() )return FILEERR_NOFILE;FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb+" : "r+" );if ( !id )return FILEERR_NOOPEN;// first find file sizefseek ( id, 0, SEEK_END );size_t fullsize = ftell ( id ), size = fullsize;fseek ( id, 0, SEEK_SET );if ( (offset + datasize) > fullsize )return FILEERR_TOSMALL;// char data[500000];#ifdef _WIN32FILE *writeId = fopen ( "temp.tmp", (m_bBinary) ? "wb" : "w" );if ( !writeId ){fclose ( id );return FILEERR_NOWRITE;}char *data = new char[offset];fread ( data, sizeof(unsigned char), offset, id );fwrite ( data, sizeof(unsigned char), offset, writeId );delete data;/*// first write the data before the filesize_t tosize = offset;while ( tosize ){int read = 500000;if ( read > tosize )read = tosize;fread ( data, sizeof(unsigned char), read, id );fwrite ( data, sizeof(unsigned char), read, writeId );tosize -= read;}*/// next fseek after and writefseek ( id, datasize, SEEK_CUR );size = fullsize - offset - datasize;data = new char[size];fread ( data, sizeof(unsigned char), size, id );fwrite ( data, sizeof(unsigned char), size, writeId );delete data;/*while ( size ){int read = 500000;if ( read > size )read = size;fread ( data, sizeof(unsigned char), read, id );fwrite ( data, sizeof(unsigned char), read, writeId );size -= read;}*/fclose ( writeId );fclose ( id );// now copy to original fileremove ( m_sFilename.c_str() );rename ( "temp.tmp", m_sFilename.c_str() );#else// move to beginning of file data to removefseek ( id, offset, SEEK_SET );size_t writepos = offset;size_t readpos = offset + datasize;size -= readpos;while ( size > 0 ){int read = 500000;if ( read > size )read = size;// read datafseek ( id, readpos, SEEK_SET );fread ( data, sizeof(unsigned char), read, id );size -= read;readpos += read;// now seek back and writefseek ( id, writepos, SEEK_SET );fwrite ( data, sizeof(unsigned char), read, id );writepos += read;}truncate ( m_sFilename.c_str(), fullsize - datasize );fclose ( id );#endifreturn FILEERR_NONE;}char *CFileIO::ReadToData ( size_t *size ){*size = 0;if ( NoFile() )return NULL;if ( !m_lSize )ReadFileSize();if ( !m_lSize )return NULL;FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb" : "r" );if ( !id )return NULL;char *data = new char[m_lSize];fread ( data, sizeof(char), m_lSize, id );if ( ferror (id) ){fclose ( id );return NULL;}*size = m_lSize;fclose ( id );return data;}bool CFileIO::WriteData ( const char *data, size_t size ){if ( NoFile() )return false;FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "wb" : "w" );if ( !id )return false;fwrite ( data, size, sizeof(char), id );fclose ( id );ReadFileSize();return true;}bool CFileIO::WriteString ( CyString data ){return WriteData ( data.c_str(), data.Length() );}bool CFileIO::Exists (){FILE *id = fopen ( m_sFilename.c_str(), (m_bBinary) ? "rb" : "r" );if ( !id )return false;fclose ( id );return true;}bool CFileIO::StartReadOld(){if ( !m_sFilename.Empty() ){if ( m_bOpened )StopRead();m_fIdOld = fopen(m_sFilename.c_str(), "rb");if ( !m_fIdOld )return false;m_bOpened = true;return true;}return false;}bool CFileIO::StartRead(){if ( !m_sFilename.Empty() ){if ( m_bOpened )StopRead();m_fId.open(m_sFilename.c_str(), std::ios_base::in);if ( m_fId.is_open() ){m_bOpened = true;return true;}}return false;}std::vector<CyString> *CFileIO::ReadLines(){if ( m_sFilename.Empty() )return 0;std::vector<CyString> *file = new std::vector<CyString>;std::string line;file->clear();std::ifstream infile (m_sFilename.c_str(), std::ios_base::in);while (getline(infile, line, '\n')){CyString l = line;l.RemoveChar((char)0);file->push_back(l);}infile.close();return file;}CyStringList *CFileIO::ReadLinesStr(){if ( m_sFilename.Empty() )return 0;CyStringList *file = new CyStringList;std::string line;std::ifstream infile (m_sFilename.c_str(), std::ios_base::in);while (getline(infile, line, '\n')){CyString l = line;l.RemoveChar((char)0);file->PushBack(l);}infile.close();return file;}void CFileIO::StopRead(){if ( m_bOpened ){if ( m_fIdOld )fclose(m_fIdOld);elsem_fId.close();}m_fIdOld = NULL;m_bOpened = false;}bool CFileIO::IsOpened(){if ( !m_bOpened )return false;if ( m_fIdOld )return true;if ( m_fId.is_open() )return true;return false;}CyString CFileIO::ReadToEndLine(bool autoclose){if ( !this->IsOpened() ){if ( !StartRead() )return "";}int pos = 0;char sLine[10000];char cur = 0;if ( m_fIdOld ){while ( !feof(m_fIdOld) ){cur = fgetc(m_fIdOld);if ( cur == '\n' || cur == '\r' )break;sLine[pos++] = cur;}}else{std::string line;if ( getline(m_fId, line, '\n') )return CyString(line);}sLine[pos] = 0;if ( pos )return CyString(sLine);if ( autoclose )StopRead();return "";}bool CFileIO::AtEnd(){if ( !m_bOpened )return true;if ( m_fIdOld ){if ( feof(m_fIdOld) )return true;}else{if ( m_fId.eof() )return true;}return false;}bool CFileIO::AppendFile ( CyString filename ){FILE *id = fopen ( filename.c_str(), (m_bBinary) ? "rb" : "r" );if ( !id )return false;FILE *aid = fopen ( m_sFilename.c_str(), (m_bBinary) ? "ab" : "a" );if ( !aid ){return false;fclose ( id );}// move to the end of the filefseek ( aid, 0, SEEK_END );// get size of filefseek ( id, 0, SEEK_END );size_t size = ftell ( id );fseek ( id, 0, SEEK_SET );char data[500000];while ( size > 0 ){size_t read = 500000;if ( read > size )read = size;size -= read;fread ( data, sizeof(char), read, id );fwrite ( data, sizeof(char), read, aid );}fclose ( aid );fclose ( id );return true;}bool CFileIO::AppendData ( const char *d, size_t size ){FILE *aid = fopen ( m_sFilename.c_str(), (m_bBinary) ? "ab" : "a" );if ( !aid )return false;// move to the end of the filefseek ( aid, 0, SEEK_END );char *pos = (char *)d;while ( size > 0 ){size_t read = 500000;if ( read > size )read = size;size -= read;fwrite ( pos, sizeof(char), read, aid );pos += read;}fclose ( aid );return true;}bool CFileIO::AppendDataToPos ( const char *d, size_t size, size_t start ){FILE *aid = fopen ( m_sFilename.c_str(), (m_bBinary) ? "ab" : "a" );if ( !aid )return false;// move to the end of the filefseek ( aid, 0, SEEK_END );size_t end = ftell(aid);if ( start > end ){fclose ( aid);return false;}fseek ( aid, start, SEEK_SET );char *pos = (char *)d;while ( size > 0 ){size_t read = 500000;if ( read > size )read = size;size -= read;fwrite ( pos, sizeof(char), read, aid );pos += read;}fclose ( aid );return true;}CyString CFileIO::GetBaseName(){return m_sFile.GetTokenRev(".", 1, -1);}CyString CFileIO::GetFileExtension (){if ( m_sFilename.Empty() )return NullString;CyString ext = m_sFilename.GetToken ( ".", m_sFilename.NumToken ( "." ) );return ext;}CyString CFileIO::ChangeFileExtension ( CyString ext ){if ( m_sFilename.Empty() )return NullString;CyString noext = m_sFilename.GetToken ( ".", 1, m_sFilename.NumToken ( "." ) - 1 );return noext + "." + ext;}bool CFileIO::Remove(){if ( !Exists() )return false;if ( remove(m_sFilename.c_str()) == 0 )return true;return false;}bool CFileIO::WriteFileUTF(std::vector<CyString> *lines){if ( !lines || m_sFilename.Empty() )return false;// we need to create the directoryif ( !m_sDirIO.Exists() ){if ( !m_sDirIO.Create() )return false;}#ifdef _WIN32TCHAR buf[5000];wsprintf(buf, L"%hs", m_sFilename.c_str());FILE *id = _wfopen(buf, L"wt+,ccs=UTF-8");if ( !id )return false;// write the restfor ( int i = 0; i < (int)lines->size(); i++ ){CyString l = lines->at(i);if ( l.IsIn('\n') ){int max;CyString *strs = l.SplitToken("\n", &max);if ( strs && max ){for ( int i = 0; i < max; i++ ){CyString line = strs[i];line += "\n";int size = wsprintf(buf, L"%hs", line.c_str());fwrite(buf, sizeof(TCHAR), wcslen(buf), id);}CLEANSPLIT(strs, max);}}else{l += "\n";int size = wsprintf(buf, L"%hs", l.c_str());fwrite(buf, sizeof(TCHAR), wcslen(buf), id);}}fclose(id);return true;#else//TODO: write utf8 file writing functionreturn false;#endif}bool CFileIO::WriteFile(std::vector<CyString> *lines){if ( !lines || m_sFilename.Empty() )return false;// we need to create the directoryif ( !m_sDirIO.Exists() ){if ( !m_sDirIO.Create() )return false;}std::ofstream out(m_sFilename.c_str());if ( !out )return false;for ( int i = 0; i < (int)lines->size(); i++ ){CyString l = lines->at(i);out << l.c_str() << std::endl;}out.close();return true;}bool CFileIO::WriteFile(CyStringList *lines){if ( !lines || m_sFilename.Empty() )return false;// we need to create the directoryif ( !m_sDirIO.Exists() ){if ( !m_sDirIO.Create() )return false;}std::ofstream out(m_sFilename.c_str());if ( !out )return false;/*if ( utf ){unsigned char smarker[4];smarker[0] = 0xEF;smarker[1] = 0xBB;smarker[2] = 0xBF;smarker[3] = 0x00;out << smarker;}*/for ( int i = 0; i < (int)lines->Count(); i++ ){CyString l = lines->StringAt(i);out << l.c_str() << std::endl;}out.close();return true;}bool CFileIO::Rename(CyString toFile){if ( rename(m_sFilename.c_str(), toFile.c_str()) == 0 )return true;return false;}CyString CFileIO::GetWindowsFilename(){CyString returnString = m_sFilename;returnString = returnString.FindReplace("/", "\\");return returnString;}void CFileIO::SetCreationTime(time_t time){#ifdef _WIN32// Note that LONGLONG is a 64-bit valueLONGLONG ll;FILETIME ft;ll = Int32x32To64(time, 10000000) + 116444736000000000;ft.dwLowDateTime = (DWORD)ll;ft.dwHighDateTime = ll >> 32;HANDLE filename = CreateFile((LPCWSTR)GetWindowsFilename().c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);// Set the file time on the fileSetFileTime(filename,(LPFILETIME) NULL,(LPFILETIME) NULL,&ft);// Close our handle.CloseHandle(filename);#endif}time_t CFileIO::GetCreationTime(){#ifdef _WIN32WIN32_FILE_ATTRIBUTE_DATA wfad;GetFileAttributesEx((LPCWSTR)GetWindowsFilename().c_str(), GetFileExInfoStandard, &wfad);LARGE_INTEGER date, adjust;date.HighPart = wfad.ftCreationTime.dwHighDateTime;date.LowPart = wfad.ftCreationTime.dwLowDateTime;// 100-nanoseconds = milliseconds * 10000adjust.QuadPart = 11644473600000 * 10000;// removes the diff between 1970 and 1601date.QuadPart -= adjust.QuadPart;// converts back from 100-nanoseconds to secondsreturn (time_t)(date.QuadPart / 10000000);#elsestruct stat fileStat;if ( !stat(GetWindowsFilename().c_str(), &fileStat) )return (time_t)fileStat.st_atime;#endifreturn 0;}/*** Copys the contents of a file to another** Reads and writes the files in block*/bool CFileIO::Copy(CyString toFile, bool keepTime){//open both filesFILE *id = fopen(GetWindowsFilename().c_str(), "rb");if ( !id )return false;FILE *toID = fopen(toFile.c_str(), "wb");if ( !toID ){fclose(id);return false;}time_t time = GetCreationTime();// get length of filefseek(id, 0, SEEK_END);size_t remainingLen = ftell(id);fseek(id, 0, SEEK_SET);if ( remainingLen <= 0 ){fclose(id);fclose(toID);return false;}// read then write a blockchar block[100000];while ( remainingLen ){size_t amt = 100000;if ( amt > remainingLen )amt = remainingLen;fread(block, amt, sizeof(char), id);fwrite(block, amt, sizeof(char), toID);remainingLen -= amt;}fclose(id);fclose(toID);if ( keepTime )CFileIO(toFile.c_str()).SetCreationTime(time);return true;}