Data Access Layer :
Data access layer (DAL) Provides simplified access to data stored in persisted storage of some kind. DAL may provide a reference to an object in terms of oops.This allows the client (or user) modules to be created with a higher level of abstraction. Achieving data abstraction for writing data to files and reading data from files is a big challenge ahead of us.Let us see how we can provide abstraction for reading and writing files in c++. Best way of encapsulation of data is done through classes.
DataWriter class:
DataWriter class provides a way to write any type of data into a file.1. Create DataWriter object.
2. Call WriteData method.
3. Close the writer.
source code :
class DataWriter
{
public:
DataWriter()
{
m_in = nullptr;
m_error = 0;
}
DataWriter(const wchar_t* fileName, const wchar_t* fileMode)
{
OpenWriter(fileName, fileMode);
}
~DataWriter()
{
CloseWriter();
}
inline void OpenWriter(const wchar_t* fileName, const wchar_t* fileMode)
{
if(!fileName)
throw std::exception("file name cant be empty");
if(!fileMode)
throw std::exception("file mode cant be empty");
m_error = _wfopen_s(&m_in, fileName, fileMode);
if(m_error == EINVAL)
{
CloseWriter();
throw std::exception("error opening file");
}
}
inline void CloseWriter()
{
if(m_in)
{
m_error = _fclose_nolock(m_in);
m_in = nullptr;
}
}
template <typename T> inline void WriteData(T* ptr, long long lengthInBytes)
{
m_error = _fwrite_nolock(ptr, lengthInBytes, 1, in);
if(m_error != lengthInBytes)
{
CloseWriter();
throw std::exception("error writing to file");
}
}
private:
FILE* m_in;
errno_t m_error;
};
DataReader class:
DataReader class provides a way to read any type of data from a file.1. Create DataReader object.
2. Call ReadData method.
3. Close the reader.
source code :
class DataReader
{
public:
DataReader()
{
m_in = nullptr;
m_error = 0;
}
DataReader(const wchar_t* fileName, const wchar_t* fileMode)
{
OpenReader(fileName, fileMode);
}
~DataReader()
{
CloseReader();
}
inline void OpenReader(const wchar_t* fileName, const wchar_t* fileMode)
{
if(!fileName)
throw std::exception("file name cant be empty");
if(!fileMode)
throw std::exception("file mode cant be empty");
m_error = _wfopen_s(&m_in, fileName, fileMode);
if(m_error == EINVAL)
{
CloseReader();
throw std::exception("error opening file");
}
}
inline void CloseReader()
{
if(m_in)
{
m_error = _fclose_nolock(m_in);
m_in = nullptr;
}
}
template <typename T> inline void ReadData(T* ptr, long long lengthInBytes)
{
m_error = _fread_nolock(ptr, lengthInBytes, 1, in);
if(m_error != lengthInBytes)
{
CloseReader();
throw std::exception("error writing to file");
}
}
private:
FILE* m_in;
errno_t m_error;
};
File Modes:
Characters
|
Equivalent oflag
|
a
|
_O_WRONLY |
_O_APPEND (usually _O_WRONLY | _O_CREAT |_O_APPEND)
|
a+
|
_O_RDWR |
_O_APPEND (usually _O_RDWR | _O_APPEND | _O_CREAT )
|
r
|
_O_RDONLY
|
r+
|
_O_RDWR
|
w
|
_O_WRONLY (usually _O_WRONLY
|_O_CREAT | _O_TRUNC)
|
w+
|
_O_RDWR (usually _O_RDWR
| _O_CREAT | _O_TRUNC)
|
b
|
_O_BINARY
|
t
|
_O_TEXT
|
S
|
_O_SEQUENTIAL
|
R
|
_O_RANDOM
|
T
|
_O_SHORTLIVED
|
D
|
_O_TEMPORARY
|
ccs=UNICODE
|
_O_WTEXT
|
ccs=UTF-8
|
_O_UTF8
|
ccs=UTF-16LE
|
_O_UTF16
|
1. Use these classes when there is need to write/read huge amounts of data from network.
2. Serialized objects can be presisted with these classes.
3. Your code contains huge collections that exceeds limit of a process boundary? above is the solution.
4. Your app contains frequent I/O operations, here is the solution.
What gain you get ?
1. These classes are nearly 8 times faster than Microsoft' s BinaryReader and BinaryWriter.
2. Can write and read any format of data, unlike Microsoft' s BinaryReader and BinaryWriter.
3. Support for UNICODE.
4. Smart class, developer need not worry about the memory release of file handle.All resources used by the class are closed/deleted when class object goes out of scope.
Good one :) Very helpful..
ReplyDelete