?? textfile.cpp
字號:
/* NOTE: If you running this in a none-Windows platform,
then you should remove the include file below.
*/
//#include <afx.h>
#include "stdafx.h"
#include "textfile.h"
#if PEK_TX_TECHLEVEL == 0
//Include iostream if running in ANSI mode.
#include <iostream>
#endif
//Base constructor
CTextFileBase::CTextFileBase()
{
#if PEK_TX_TECHLEVEL > 0
m_codepage = CP_ACP;
m_unknownChar = 0;
#else
m_unknownChar = '?';
#endif
#if PEK_TX_TECHLEVEL == 1
m_hFile = INVALID_HANDLE_VALUE;
#elif PEK_TX_TECHLEVEL == 2
m_file = NULL;
m_closeAndDeleteFile = false;
#endif
m_datalost = false;
m_buffpos = -1;
}
//Base destructor
CTextFileBase::~CTextFileBase()
{
Close();
}
//Set which character to use when conversion can't be done
void CTextFileBase::SetUnknownChar(const char unknown)
{
m_unknownChar = unknown;
}
//True if data was lost during conversion
bool CTextFileBase::IsDataLost() const
{
return m_datalost;
}
//Reset the data lost flag
void CTextFileBase::ResetDataLostFlag()
{
m_datalost = false;
}
#if PEK_TX_TECHLEVEL > 0
//Make sure we have a legal value for code page to use when
//converting string. Used for debugging only.
#define IsLegalCodePage(cp) (cp == CP_ACP || cp == CP_MACCP || cp == CP_OEMCP || cp == CP_SYMBOL || cp == CP_THREAD_ACP || cp == CP_UTF7 || cp == CP_UTF8 || IsValidCodePage(cp))
#ifndef ASSERT
#define ASSERT 0
#endif
//(Windows-specific) Set codepage to use when working with non-unicode strings.
void CTextFileBase::SetCodePage(const UINT codepage)
{
ASSERT(IsLegalCodePage(codepage));
m_codepage = codepage;
}
//(Windows-specific) Get codepage to use when working with non-unicode strings.
UINT CTextFileBase::GetCodePage() const
{
return m_codepage;
}
//(Windows-specific) Convert string to wstring with current codepage
inline void CTextFileBase::CharToWstring(const char* from, wstring &to) const
{
ConvertCharToWstring(from, to, m_codepage);
}
//(Windows-specific) Convert wstring to string with current codepage
inline void CTextFileBase::WcharToString(const wchar_t* from, string &to)
{
ConvertWcharToString(from, to, m_codepage, &m_datalost, m_unknownChar);
}
//(Windows-specific) Convert char* to wstring
void CTextFileBase::ConvertCharToWstring(const char* from, wstring &to, UINT codepage)
{
to = L"";
ASSERT(IsLegalCodePage(codepage));
//Use api convert routine
int wlen = MultiByteToWideChar( codepage,
0,
from,
-1,
NULL,
0);
//if wlen == 0, some unknown codepage was probably used.
ASSERT(wlen);
if(wlen == 0)
return;
wchar_t* wbuffer = new wchar_t[wlen+2];
MultiByteToWideChar( codepage,
0,
from,
-1,
wbuffer,
wlen);
to = wbuffer;
delete [] wbuffer;
}
//(Windows-specific) Convert wchar_* to string
void CTextFileBase::ConvertWcharToString(const wchar_t* from, string &to,
UINT codepage, bool* datalost, char unknownchar)
{
to = "";
ASSERT(IsLegalCodePage(codepage));
int alen = WideCharToMultiByte( codepage,
0,
from,
-1,
NULL,
0,
NULL,
NULL);
//if alen == 0, some unknown codepage was probably used.
ASSERT(alen);
if(alen == 0)
return;
//Use mfc convert routine
char* abuffer = new char[alen+2];
BOOL UsedDefault=FALSE;
WideCharToMultiByte( codepage,
0,
from,
-1,
abuffer,
alen,
(unknownchar != 0 ? &unknownchar : NULL),
(datalost != NULL ? &UsedDefault : NULL)
);
if( datalost != NULL && UsedDefault != FALSE)
*datalost = true;
to = abuffer;
delete [] abuffer;
}
#else
//(None-windows-specific) Convert string to wstring
inline void CTextFileBase::CharToWstring(const char* from, wstring &to) const
{
ConvertCharToWstring(from, to);
}
//(None-windows-specific) Convert wstring to string
inline void CTextFileBase::WcharToString(const wchar_t* from, string &to)
{
ConvertWcharToString(from, to, &m_datalost, m_unknownChar);
}
//(None-windows-specific) Convert char* to wstring
void CTextFileBase::ConvertCharToWstring(const char* from, wstring &to)
{
to = L"";
size_t pos=0;
wchar_t temp[1];
while(true)
{
size_t len = mbtowc(temp, from+pos, MB_CUR_MAX);
//Found end
if(len == 0)
return;
else if(len == (size_t)-1)
{
//Unknown character, should never happen
pos++;
}
else
{
to += temp[0];
pos += len;
}
}
}
//(None-windows-specific) Convert wchar_* to string
void CTextFileBase::ConvertWcharToString(const wchar_t* from, string &to, bool* datalost, char unknownchar)
{
to = "";
char* temp = new char[MB_CUR_MAX];
while(*from != L'\0')
{
size_t len = wctomb(temp, *from);
//Found end
if(len == 0)
break;
else if(len == (size_t)-1)
{
//Replace with unknown character
to += unknownchar;
if(datalost != NULL)
*datalost=true;
}
else
{
//Copy all characters
for(size_t i=0; i<len; i++)
to += temp[i];
}
from++;
}
delete [] temp;
}
#endif
//Return file encoding
CTextFileBase::TEXTENCODING CTextFileBase::GetEncoding() const
{
return m_encoding;
};
//Is file open?
int CTextFileBase::IsOpen()
{
#if PEK_TX_TECHLEVEL == 0
return m_file.is_open();
#elif PEK_TX_TECHLEVEL == 1
return m_hFile != INVALID_HANDLE_VALUE;
#else
return (m_file != NULL && m_file->m_hFile != CFile::hFileNull);
#endif
}
//Close file
void CTextFileBase::Close()
{
if(IsOpen())
{
#if PEK_TX_TECHLEVEL == 0
m_file.close();
#elif PEK_TX_TECHLEVEL == 1
::CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
#else
if(m_closeAndDeleteFile)
{
m_file->Close();
}
#endif
}
#if PEK_TX_TECHLEVEL == 2
if(m_closeAndDeleteFile)
{
delete m_file;
m_file = NULL;
}
#endif
}
//Create textfile
CTextFileWrite::CTextFileWrite(const FILENAMECHAR* filename, TEXTENCODING encoding)
{
#if PEK_TX_TECHLEVEL == 0
m_file.open(filename, ios::binary | ios::out );
#elif PEK_TX_TECHLEVEL == 1
m_hFile = ::CreateFile( filename,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
#else
m_file = new CFile;
m_file->Open(filename, CFile::modeCreate | CFile::modeWrite);
m_closeAndDeleteFile = true;
#endif
m_buffpos = -1;
m_buffsize = 0;
m_encoding = encoding;
WriteBOM();
}
#if PEK_TX_TECHLEVEL==2
//Create textfile from CFile object
CTextFileWrite::CTextFileWrite(CFile* file, TEXTENCODING encoding)
{
ASSERT(file);
m_file = file;
m_closeAndDeleteFile = false;
m_encoding = encoding;
m_buffpos = -1;
m_buffsize = 0;
WriteBOM();
}
#endif
CTextFileWrite::~CTextFileWrite()
{
Close();
}
void CTextFileWrite::WriteBOM()
{
//Write BOM
if(IsOpen())
{
if(m_encoding == UNI16_BE || m_encoding == UNI16_LE)
{
//Write BOM
WriteWchar( 0xFEFF );
}
else if(m_encoding == UTF_8)
{
//Write UTF-8 BOM. 0xEF 0xBB 0xBF
WriteByte(0xEF);
WriteByte(0xBB);
WriteByte(0xBF);
}
}
}
//Write one byte
void CTextFileWrite::WriteByte(const unsigned char byte)
{
//Instead of writing, save data in buffer and write when buffer is full
if(m_buffpos+1 >= BUFFSIZE)
Flush();
m_buffpos++;
m_buf[m_buffpos] = byte;
}
//Write and empty buffer
void CTextFileWrite::Flush()
{
#if PEK_TX_TECHLEVEL==0
m_file.write(m_buf, m_buffpos+1);
#elif PEK_TX_TECHLEVEL==1
DWORD nWritten;
if (!::WriteFile(m_hFile, m_buf, m_buffpos+1, &nWritten, NULL))
{
//Something bad has happend! Close file
CTextFileBase::Close();
//Throw exception
throw CTextFileException(GetLastError());
}
#else
m_file->Write(m_buf, m_buffpos+1);
#endif
m_buffpos = -1;
}
void CTextFileWrite::WriteWchar(const wchar_t ch)
{
//Write HO byte first?
if(m_encoding == UNI16_BE)
{
//Write HO byte
WriteByte((unsigned char) (ch >> 8) );
//Write LO byte
WriteByte((unsigned char) ch);
}
else if(m_encoding == UNI16_LE)
{
//Write LO byte
WriteByte((unsigned char) ch);
//Write HO byte
WriteByte((unsigned char) (ch >> 8) );
}
else
{
//http://www.cl.cam.ac.uk/~mgk25/unicode.html#examples
//http://www.ietf.org/rfc/rfc3629.txt
//Just a single byte?
if(ch <= 0x7F)
{
//U-00000000 - U-0000007F: 0xxxxxxx
WriteByte( (unsigned char) ch );
}
//Two bytes?
else if(ch <= 0x7FF)
{
//U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
WriteByte( (unsigned char) (0xC0 | (ch>>6)) );
WriteByte( (unsigned char) (0x80 | (ch&0x3F)) );
}
//Three bytes?
else if(ch <= 0xFFFF)
{
//U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
WriteByte( (unsigned char) (0xE0 | ( ch>>12) ));
WriteByte( (unsigned char) (0x80 | ( (ch>>6)&0x3F ) ));
WriteByte( (unsigned char) (0x80 | ( ch&0x3F ) ));
}
/* //UPS! I did some coding for UTF-32, may be useful in the future :-)
//Four bytes?
else if(ch <= 0x1FFFFF)
{
//U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
WriteByte( (unsigned char) (0xF0 | ( ch>>18) ));
WriteByte( (unsigned char) (0xA0 | ( (ch>>12)&0xA0 ) ));
WriteByte( (unsigned char) (0xA0 | ( (ch>>6)&0xA0 ) ));
WriteByte( (unsigned char) (0xA0 | ( ch&0xA0 ) ));
}
//Five bytes bytes?
else if(ch <= 0x3FFFFFF)
{
//U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
WriteByte( (unsigned char) (0xF8 | ( ch>>24) ));
WriteByte( (unsigned char) (0xA0 | ( (ch>>18)&0xA0 ) ));
WriteByte( (unsigned char) (0xA0 | ( (ch>>12)&0xA0 ) ));
WriteByte( (unsigned char) (0xA0 | ( (ch>>6)&0xA0 ) ));
WriteByte( (unsigned char) (0xA0 | ( ch&0xA0 ) ));
}
//Five bytes bytes?
else if(ch <= 0x7FFFFFFF)
{
//U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
WriteByte( (unsigned char) (0xFC | ( ch>>30) ));
WriteByte( (unsigned char) (0xA0 | ( (ch>>24)&0xA0 ) ));
WriteByte( (unsigned char) (0xA0 | ( (ch>>18)&0xA0 ) ));
WriteByte( (unsigned char) (0xA0 | ( (ch>>12)&0xA0 ) ));
WriteByte( (unsigned char) (0xA0 | ( (ch>>6)&0xA0 ) ));
WriteByte( (unsigned char) (0xA0 | ( ch&0xA0 ) ));
}*/
}
}
//Write new line
void CTextFileWrite::WriteEndl()
{
if(m_encoding == ASCII)
{
WriteByte(0x0D);
WriteByte(0x0A);
}
else
{
WriteWchar(0x0D);
WriteWchar(0x0A);
}
}
//Write a c-string in ASCII.
//In versions before 1.02 this function wrote directly to file,
//no buffer was used. But sense WriteEndl() used buffer the file was
//written incorretly. Now buffer is used here too, this is the
//fastest solution.
void CTextFileWrite::WriteAsciiString(const char* s)
{
while(*s != '\0')
{
WriteByte(*s);
s++;
}
}
CTextFileWrite& CTextFileWrite::operator<< (const char* text)
{
Write(text);
return *this;
};
CTextFileWrite& CTextFileWrite::operator << (const string& text)
{
Write(text.c_str());
return *this;
}
CTextFileWrite& CTextFileWrite::operator<< (const wchar_t* text)
{
Write(text);
return *this;
};
CTextFileWrite& CTextFileWrite::operator << (const wstring& text)
{
Write(text.c_str());
return *this;
}
CTextFileWrite& CTextFileWrite::operator<< (const wchar_t wc)
{
//Not the perfect code, but it's easy!
wstring text;
text=wc;
Write(text.c_str());
return *this;
};
CTextFileWrite& CTextFileWrite::operator<< (const char c)
{
//Not the perfect code, but it's easy!
string text;
text=c;
Write(text.c_str());
return *this;
};
void CTextFileWrite::Write(const string& text)
{
Write(text.c_str());
}
void CTextFileWrite::Write(const wstring& text)
{
Write(text.c_str());
}
//Write char*
void CTextFileWrite::Write(const char* text)
{
//ASCIItext file format?
if(m_encoding == ASCII)
WriteAsciiString(text);
else
{
//Convert text to unicode
wstring utext;
CharToWstring(text, utext);
//OK, lets write unicode
for(wstring::const_iterator i=utext.begin();
i < utext.end();
i++)
{
WriteWchar(*i);
}
}
}
//Write wcar_t*
void CTextFileWrite::Write(const wchar_t* utext)
{
//ASCII text file format?
if(m_encoding == ASCII)
{
//Convert to string and write
string text;
WcharToString(utext, text);
WriteAsciiString(text.c_str());
}
else
{
while(*utext != 0)
{
WriteWchar(*utext);
utext++;
}
}
}
//Close the file
void CTextFileWrite::Close()
{
if(IsOpen())
Flush();
CTextFileBase::Close();
}
CTextFileRead::CTextFileRead(const FILENAMECHAR* filename)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -