Rev 57 | Rev 82 | 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_lSize(0), m_bBinary(true), m_bAutoDelete(false), m_bSeekP(false){}/*CFileIO::CFileIO(const Utils::String &sFilename, bool bBinary = true) : m_lSize(0), m_bBinary(bBinary), m_bAutoDelete(false){Open(sFilename, bBinary);}*/CFileIO::CFileIO(CyString filename) : m_lSize(0), m_bBinary(true), m_bAutoDelete(false), m_bSeekP(false){Open(filename, true);}CFileIO::CFileIO(C_File *file) : m_lSize(0), m_bBinary(true), m_bAutoDelete(false), m_bSeekP(false){Open(file->GetFilePointer(), true);}CFileIO::~CFileIO(){if ( this->isOpened() ) m_fId.close();if ( m_bAutoDelete ) this->remove();}void CFileIO::setAutoDelete(bool bDelete){m_bAutoDelete = true;}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;}unsigned char *CFileIO::read(size_t iAmount){if ( !this->isOpened() ) startRead();if ( !this->isOpened() ) return NULL;if ( iAmount > m_lSize ) iAmount = m_lSize;unsigned char *data;try {data = new unsigned char[iAmount + 1];}catch (std::exception &e) {CLog::logf(CLog::Log_IO, 2, "ERROR: CFileIO::read(size_t) unable to malloc data, %d (%s)", iAmount + 1, e.what());return NULL;}if ( !read(data, iAmount, true) ) {CLog::logf(CLog::Log_IO, 2, "ERROR: CFileIO::read(size_t) unable to read data from file, %s/%d", m_sFilename.c_str(), iAmount);delete data;return NULL;}return data;}unsigned char *CFileIO::readAll(size_t *pSize){if ( pSize ) (*pSize) = 0;if ( !this->isOpened() ) startRead();if ( !this->isOpened() ) return NULL;unsigned char *data;try {data = new unsigned char[m_lSize + 1];}catch (std::exception &e) {CLog::logf(CLog::Log_IO, 2, "ERROR: CFileIO::readAll() unable to malloc data, %d (%s)", m_lSize + 1, e.what());return NULL;}if ( !read(data, m_lSize, true) ) {CLog::logf(CLog::Log_IO, 2, "ERROR: CFileIO::readAll() unable to read data from file, %s/%d", m_sFilename.c_str(), m_lSize);delete data;return NULL;}if ( pSize ) (*pSize) = m_lSize;return data;}bool CFileIO::read(unsigned char *buf, size_t iSize, bool bEndChar){if ( !this->isOpened() ) startRead();if ( !this->isOpened() ) return false;if ( iSize > m_lSize ) iSize = m_lSize;try {m_fId.read((char *)buf, iSize);}catch (std::exception &e) {CLog::logf(CLog::Log_IO, 3, "ERROR: CFileIO::read() unable to read from file: %s (%s)", m_sFilename.c_str(), e.what());return false;}if ( bEndChar ) buf[iSize] = '\0';return !m_fId.bad();}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;if ( !this->startRead() ) return FILEERR_NOOPEN;if ( (offset + datasize) > m_lSize ) return FILEERR_TOSMALL;CFileIO File("temp.tmp");if ( !File.startWrite() ) return FILEERR_NOWRITE;File.setAutoDelete(true);if ( !File.write(*this, offset) ) return false;// next fseek after and writethis->seek(datasize);size_t size = m_lSize - offset - datasize;if ( size > 0 ) {File.write(*this, size);}File.close();this->close();File.setAutoDelete(false);// now copy to original fileif ( std::remove(m_sFilename.c_str()) == 0 ) {std::rename("temp.tmp", m_sFilename.c_str());return FILEERR_NONE;}return FILEERR_NOWRITE;}int CFileIO::_in() const{if ( m_bBinary ) return std::ios::in | std::ios::binary;return std::ios::in;}int CFileIO::_out() const{if ( m_bBinary ) return std::ios::out | std::ios::binary;return std::ios::out;}int CFileIO::_inout() const{if ( m_bBinary ) return std::ios::in | std::ios::out | std::ios::binary;return std::ios::in | std::ios::out;}int CFileIO::_append() const{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(const Utils::String &filename){std::fstream File(filename, std::ios::in | std::ios::binary);bool bRet = File.good();File.close();return bRet;}bool CFileIO::ExistsOld () const{return this->exists();}bool CFileIO::exists () const{if ( this->isOpened() ) return true;std::fstream File(m_sFilename, _in());bool bRet = File.good();File.close();return bRet;}bool CFileIO::StartRead() { return startRead(); }bool CFileIO::startRead(){return _start(_in(), false);}bool CFileIO::startWrite(){return _start(_out(), true);}bool CFileIO::startModify(){return _start(_inout(), true);}bool CFileIO::startAppend(){return _start(_append(), false);}bool CFileIO::_start(int iFlags, bool bSeekP){if ( !m_sFilename.empty() ) {if ( this->isOpened() ) this->close();m_fId.open(m_sFilename, iFlags);}m_bSeekP = bSeekP;return m_fId.is_open();}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;}bool CFileIO::put(const unsigned char c){if ( !this->isOpened() ) return false;m_fId.put(c);return !m_fId.bad();}bool CFileIO::writeSize(unsigned int iSize){if ( !this->isOpened() ) return false;if ( !this->put(static_cast<unsigned char>(iSize >> 24)) ) return false;if ( !this->put(static_cast<unsigned char>(iSize >> 16)) ) return false;if ( !this->put(static_cast<unsigned char>(iSize >> 8)) ) return false;if ( !this->put(static_cast<unsigned char>(iSize)) ) return false;m_lSize += 4;return true;}bool CFileIO::write(CFileIO &file, size_t iSize){if ( !this->isOpened() ) startWrite();if ( !this->isOpened() ) return false;int iMaxSize = 1000000;unsigned char *data;try {data = new unsigned char[iMaxSize + 1];}catch (std::exception &e) {CLog::logf(CLog::Log_IO, 2, "ERROR: CFileIO::write(CFileIO, size_t) unable to malloc data, %d (%s)", iMaxSize + 1, e.what());return false;}int iSizeLeft = iSize;bool bSuccess = true;while ( iSizeLeft > 0 ) {int iDoSize = iMaxSize;if ( iDoSize > iSizeLeft ) iDoSize = iSizeLeft;if ( !file.read(data, iDoSize) ) bSuccess = false;if ( bSuccess && !this->write(data, iDoSize) ) bSuccess = false;if ( !bSuccess ) break;m_lSize += iDoSize;iSizeLeft -= iDoSize;}delete data;return bSuccess;}bool CFileIO::write(const char *buf, unsigned int iSize){if ( !this->isOpened() ) startWrite();if ( !this->isOpened() ) return false;try {m_fId.write((char *)buf, iSize);}catch (std::exception &e) {CLog::logf(CLog::Log_IO, 2, "CFileIO::write() unable to write to file: %s (%s)", m_sFilename.c_str(), e.what());return false;}m_lSize += iSize;return !m_fId.bad();}bool CFileIO::write(const unsigned char *buf, unsigned int iSize){return this->write((char *)buf, iSize);}bool CFileIO::write(const unsigned char *buf, ...){va_list args;va_start(args, buf);bool ret = this->_write((char *)buf, args);va_end(args);return ret;}bool CFileIO::_write(const char *buf, va_list args){if ( !this->isOpened() ) return false;char buffer[10000];vsprintf (buffer, buf, args);try {int iLen = strlen(buffer);m_fId.write((char *)buffer, iLen);m_lSize += iLen;}catch (std::exception &e) {CLog::logf(CLog::Log_IO, 2, "CFileIO::write() unable to write to file: %s (%s)", m_sFilename.c_str(), e.what());return false;}return !m_fId.bad();}bool CFileIO::write(const char *buf, ...){va_list args;va_start(args, buf);bool ret = this->_write((char *)buf, args);va_end(args);return ret;}void CFileIO::_seek(int iPos, int iFrom){if ( !this->isOpened() ) {if ( !this->startRead() ) return;}if ( m_bSeekP ) m_fId.seekp(iPos, iFrom);else m_fId.seekg(iPos, iFrom);}void CFileIO::seek(unsigned int iPos){_seek(iPos, std::ios::cur);}void CFileIO::seekEnd(unsigned int iPos){_seek(iPos, std::ios::end);}void CFileIO::seekStart(unsigned int iPos){_seek(iPos, std::ios::beg);}std::fstream &CFileIO::stream(){return m_fId;}void CFileIO::StopRead(){this->close();}bool CFileIO::isOpened() const{if ( m_fId.is_open() )return true;return false;}void CFileIO::close(){if ( this->isOpened() ) m_fId.close();}int CFileIO::readSize(){unsigned char size[4];if ( this->read(size, 4) ) return (size[0] << 24) + (size[1] << 16) + (size[2] << 8) + size[3];return 0;}bool CFileIO::AtEnd() const{return this->atEnd();}bool CFileIO::atEnd() const{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::ofstream File(m_sFilename, _append());if ( !File.is_open() ) return false;// move to the end of the file//File.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 ){if ( start > m_lSize ) return false;if ( m_lSize <= 0 ) {if ( !this->startWrite() ) return false;}else if ( start == m_lSize ) {if ( !this->startAppend() ) return false;}else {if ( !this->startModify() ) return false;this->seekStart(start);}return this->write(d, size);}Utils::String CFileIO::readEndOfLine(){if ( !this->isOpened() ) {if ( !StartRead() ) return "";}Utils::String str;std::getline(m_fId, str, '\n');return str;}Utils::String CFileIO::baseName() const{return m_sFile.token(".", -2);}CyString CFileIO::GetFileExtension (){if ( m_sFilename.empty() ) return NullString;return m_sFilename.token(".", -1);}Utils::String CFileIO::extension (){if ( m_sFilename.empty() ) return "";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(const Utils::String &rem){//if ( !Exists() ) return false;return (std::remove(rem) == 0) ? true : false;}bool CFileIO::remove(){if ( this->isOpened() ) this->close();if ( !this->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;WCHAR str[MAX_PATH];MultiByteToWideChar(CP_ACP, NULL, GetWindowsFilename().c_str(), -1, str, GetWindowsFilename().Length() + 1);HANDLE filename = CreateFile(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(){return modifiedTime();}time_t CFileIO::modifiedTime(){#ifdef _WIN32WCHAR str[MAX_PATH];MultiByteToWideChar(CP_ACP, NULL, GetWindowsFilename().c_str(), -1, str, GetWindowsFilename().Length() + 1);WIN32_FILE_ATTRIBUTE_DATA wfad;GetFileAttributesEx(str, GetFileExInfoStandard, &wfad);LARGE_INTEGER date, adjust;date.HighPart = wfad.ftLastWriteTime.dwHighDateTime;date.LowPart = wfad.ftLastWriteTime.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;}size_t CFileIO::position(){return m_fId.tellg();}/*** Copys the contents of a file to another** Reads and writes the files in block*/bool CFileIO::copy(const Utils::String &toFile, bool keepTime){time_t time = GetCreationTime();CFileIO File(toFile);if ( File.write(*this, m_lSize) ) {if ( keepTime ) File.SetCreationTime(time);return true;}/*std::fstream f(GetWindowsFilename().c_str(), std::fstream::in | std::fstream::binary);f << std::noskipws;std::istream_iterator<unsigned char> begin(f);std::istream_iterator<unsigned char> end;std::fstream f2(toFile.c_str(), std::fstream::out | std::fstream::trunc | std::fstream::binary);std::ostream_iterator<char> begin2(f2);std::copy(begin, end, begin2);return f2.good();*/return false;}size_t CFileIO::fileSize() const{return m_lSize;}