Rev 42 | Rev 52 | 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"#include "Logging/Log.h"CFileIO::CFileIO () : m_bOpened(false), m_lSize(0), m_bBinary(true){}CFileIO::CFileIO(CyString filename) : m_bOpened(false), m_lSize(0), m_bBinary(true){Open ( filename, true );}CFileIO::CFileIO(C_File *file) : m_bOpened(false), m_lSize(0), m_bBinary(true){Open ( file->GetFilePointer(), true );}CFileIO::~CFileIO(){if ( m_bOpened ) m_fId.close();}bool CFileIO::Open ( CyString filename, bool binary ){m_bBinary = binary;m_sFilename = filename.ToString();m_sFilename = m_sFilename.findReplace("\\", "/");m_sFilename = m_sFilename.findReplace("//", "/");if ( m_sFilename.isin('/') ) {m_sDirIO.SetDir(m_sFilename.tokens("/", 1, -2));m_sFile = m_sFilename.token("/", -1);}elsem_sFile = filename.ToString();this->_readFileSize();return true;}bool CFileIO::WritePartFile ( size_t *offsets, size_t numOffset ){if ( NoFile() ) return false;std::fstream File(m_sFilename, _in());if ( !File.is_open() ) return false;// first find file sizeFile.seekg(0, std::ios::end);size_t fullsize = File.tellg(), size = fullsize;File.seekg(0, std::ios::beg);std::fstream writeFile("temp.tmp", _out());if ( !File.is_open() ) {File.close();return false;}size_t off = 0;size_t startPos = 0;size_t remainingSize = fullsize;while ( off < numOffset ) {startPos = File.tellg();size_t offset = offsets[off++];size_t size = offset - startPos;try {char *data = new char[size];File.read(data, size);writeFile.write(data, size);delete data;}catch(std::exception &e) {CLog::logf(CLog::Log_IO, 2, "CFileIO::WritePartFilea() unable to read data from file: %s (%s)", m_sFilename.c_str(), e.what());return false;}size_t datasize = offsets[off++];File.seekg(datasize, std::ios::beg);remainingSize = fullsize - offset - datasize;}if ( remainingSize ) {char data[1000000];size_t amountLeft = 1000000;while ( remainingSize ){if ( amountLeft > remainingSize ) amountLeft = remainingSize;try {File.read(data, amountLeft);writeFile.write(data, amountLeft);}catch(std::exception &e) {CLog::logf(CLog::Log_IO, 2, "CFileIO::WritePartFilea() unable to read data from file: %s (%s)", m_sFilename.c_str(), e.what());return false;}remainingSize -= amountLeft;amountLeft = 1000000;}}File.close();writeFile.close();// now copy to original filestd::remove(m_sFilename);std::rename("temp.tmp", m_sFilename);return true;}void CFileIO::SetDir ( CyString dir ){if ( m_sFile.empty() ) m_sDirIO.SetDir(dir);else Open(dir + "/" + m_sFile, m_bBinary);}void CFileIO::_readFileSize (){m_lSize = 0;std::fstream file(m_sFilename, (m_bBinary) ? (std::ios::in | std::ios::binary) : (std::ios::in));if ( !file.is_open() ) return;file.seekg(0, std::ios::end);m_lSize = file.tellg();file.close();}bool CFileIO::WipeFile(){if ( NoFile() ) return false;std::ofstream file;file.open(m_sFilename, std::ios::out | std::ios::trunc);bool bDone = file.is_open();file.close();return bDone;}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;// next fseek after and writefseek ( id, datasize, SEEK_CUR );size = fullsize - offset - datasize;if ( size > 0 ) {data = new char[size];fread ( data, sizeof(unsigned char), size, id );fwrite ( data, sizeof(unsigned char), size, writeId );delete data;}fclose ( writeId );fclose ( id );// now copy to original filestd::remove(m_sFilename.c_str());std::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;}int CFileIO::_in(){if ( m_bBinary ) return std::ios::in | std::ios::binary;return std::ios::in;}int CFileIO::_out(){if ( m_bBinary ) return std::ios::out | std::ios::binary;return std::ios::out;}int CFileIO::_append(){if ( m_bBinary ) return std::ios::out | std::ios::binary | std::ios::app;return std::ios::out | std::ios::app;}char *CFileIO::ReadToData ( size_t *size ){*size = 0;if ( NoFile() ) return NULL;if ( !m_lSize ) this->_readFileSize();if ( !m_lSize ) return NULL;std::fstream file(m_sFilename, _in());if ( !file.is_open() ) return NULL;char *data;try {data = new char[m_lSize + 1];}catch (std::exception &e) {CLog::logf(CLog::Log_IO, 2, "CFileIO::ReadToData() unable to malloc storage, %d (%s)", m_lSize + 1, e.what());file.close();return NULL;}try {file.read((char *)data, m_lSize);}catch (std::exception &e) {CLog::logf(CLog::Log_IO, 2, "CFileIO::ReadToData() unable to read data from file (%s)", e.what());file.close();return NULL;}*size = m_lSize;file.close();return data;}bool CFileIO::WriteData ( const char *data, size_t size ){if ( NoFile() )return false;std::fstream File(m_sFilename, _out());if ( !File.is_open() ) return false;bool ret = true;try {File.write(data, size);}catch (std::exception &e) {CLog::logf(CLog::Log_IO, 2, "CFileIO::ReadToData() unable to read data from file: %s (%s)", m_sFilename.c_str(), e.what());ret = false;}File.close();if ( ret ) this->_readFileSize();return ret;}bool CFileIO::WriteString ( CyString data ){return WriteData ( data.c_str(), data.Length() );}bool CFileIO::Exists (){std::fstream File(m_sFilename, _in());bool bRet = File.good();File.close();return bRet;}bool CFileIO::StartRead(){if ( !m_sFilename.empty() ) {if ( m_bOpened ) StopRead();m_fId.open(m_sFilename, _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_fId.is_open() ) m_fId.close();m_bOpened = false;}bool CFileIO::IsOpened(){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;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 ( !this->IsOpened() ) return true;if ( m_fId.eof() ) return true;return false;}bool CFileIO::AppendFile ( CyString filename ){std::fstream fromFile(filename.ToString().c_str(), _in());if ( !fromFile.is_open() ) return false;std::fstream toFile(m_sFilename, _append());if ( !toFile.is_open() ) {fromFile.close();return false;}// move to the end of the filetoFile.seekg(0, std::ios::end);// get size of filefromFile.seekg(0, std::ios::end);size_t size = fromFile.tellg();fromFile.seekg(0, std::ios::beg);char data[500000];while ( size > 0 ){size_t read = 500000;if ( read > size )read = size;size -= read;fromFile.read(data, read);toFile.write(data, read);}fromFile.close();toFile.close();return true;}bool CFileIO::AppendData ( const char *d, size_t size ){std::fstream File(m_sFilename, _append());if ( !File.is_open() ) return false;// move to the end of the fileFile.seekg(0, std::ios::end);char *pos = (char *)d;while ( size > 0 ) {size_t read = 500000;if ( read > size ) read = size;size -= read;try {File.write(pos, read);}catch(std::exception &e) {CLog::logf(CLog::Log_IO, 2, "CFileIO::AppendData() unable to write data to file: %s (%s)", m_sFilename.c_str(), e.what());File.close();return false;}pos += read;}File.close();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;}if ( start == end ) {fseek(aid, 0, SEEK_END);}else {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.token(".", -2);}CyString CFileIO::GetFileExtension (){if ( m_sFilename.empty() ) return NullString;return m_sFilename.token(".", -1);}CyString CFileIO::ChangeFileExtension ( CyString ext ){if ( m_sFilename.empty() )return NullString;return m_sFilename.tokens(".", 1, -2) + "." + ext.ToString();}bool CFileIO::Remove(){if ( !Exists() )return false;if ( std::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;}