Writing a class to Random Access File via reinterpret_cast

Aim
The aim of this tutorial is to create a template that can be used to write and read classes to and from a random access file. This tutorial can be used as an introduction to templates, reinterpret_casting from classes to char array and how to implement a random access file.

The first file is TRandomAccess.hpp and it contains all the template code. The second file main.c is an example of how to use the templates.

The basic idea is to cast the classes into byte arrays via reinterpret_cast and then write them to a file. Using fseek we then travel to any point of the file to retrieve or write a class.
 1. /*Righteous Ninja AKA P.S. Ching codediaries.com*/
 2. 
 3. #ifndef TRANDOMACCESS_H
 4. #define TRANDOMACCESS_H
 5. 
 6. 
 7. #include <stdio.h>
 8. 
 9. #define    RADOMPOS_APPEND    -1
10. #define RANDOMF_ERROR    int
11. 
12. enum{
13.     RANDOMF_OK=0, RANDOMF_OPENERR, RANDOMF_SEEKERR, RANDOMF_EOFERR, RANDOMF_BADPOINTER
14. };
15. 
16. template < class T>
17. class TRandomAccess{
18. public:
19.     TRandomAccess();
20.     ~TRandomAccess();
21. 
22. public:
23.     RANDOMF_ERROR Open(char*);
24.     void Close();
25.     RANDOMF_ERROR Write( T*, int=RADOMPOS_APPEND);
26.     RANDOMF_ERROR Read( T*, int);
27.     RANDOMF_ERROR ReadNext(T*);
28.     void ResetReadNext(int);
29. 
30. protected:
31.     FILE* random_fp;
32.     int   nextPosition;
33. };
34. 
35. template <class T> TRandomAccess<T>::TRandomAccess(){
36. }
37. 
38. template <class T> TRandomAccess<T>::~TRandomAccess(){
39. }
40. 
41. template <class T> RANDOMF_ERROR TRandomAccess<T>::Write(T* in_t, int position){
42.     if(position == RADOMPOS_APPEND){
43.         if( fseek(random_fp, 0, SEEK_END ) != 0)
44.             return RANDOMF_SEEKERR;
45.         char* tmps = reinterpret_cast<char*>(in_t);
46.         fwrite(tmps, sizeof(T), 1, random_fp);
47.     }
48.     else{
49.         if( fseek(random_fp, position*sizeof(T), SEEK_SET ) != 0)
50.             return RANDOMF_SEEKERR;
51.         char* tmps = reinterpret_cast<char*>(in_t);
52.         fwrite(tmps, sizeof(T), 1, random_fp);
53.         fflush(random_fp);
54.     }
55.     return RANDOMF_OK;
56. }
57. 
58. template <class T> RANDOMF_ERROR TRandomAccess<T>::Read(T* in_t, int position){
59.     char tmps[sizeof(T)];
60.     if( fseek(random_fp, position*sizeof(T), SEEK_SET ) != 0)
61.         return RANDOMF_SEEKERR;
62.     if( fread(tmps, sizeof(T),1, random_fp) == 0 )
63.         return RANDOMF_EOFERR;
64.     if(in_t!=0){
65.         memcpy(in_t, reinterpret_cast<T*>(tmps), sizeof(T));
66.         return RANDOMF_OK;
67.     }
68.     else{
69.         return RANDOMF_BADPOINTER;
70.     }
71. }
72. 
73. template <class T> void TRandomAccess<T>::ResetReadNext(int t){
74.     nextPosition=t;
75. }
76. 
77. template <class T> RANDOMF_ERROR TRandomAccess<T>::ReadNext(T* in_t){
78.     return Read(in_t, nextPosition++);
79. }
80. 
81. template <class T> RANDOMF_ERROR TRandomAccess<T>::Open(char* filename){
82.     random_fp = fopen(filename, "r+");
83.     if( random_fp == 0 ){
84.         random_fp = fopen(filename, "w");
85.         if( random_fp == 0 ){
86.             return RANDOMF_OPENERR; 
87.         }
88.         return RANDOMF_OK;
89.     }
90.     else
91.         return RANDOMF_OK;
92. }
93. 
94. template <class T> void TRandomAccess<T>::Close(){
95.     fflush(random_fp);
96.     fclose(random_fp);    
97. }
98. 
99. #endif
Hide line numbers

Below is the main.c, which shows how to use the TRandomAccess template.
 1. #include <time.h>
 2. #include <string.h>
 3. #include <stdio.h>
 4. #include <stdlib.h>
 5. 
 6. #include "TRandomAccess.hpp"
 7. 
 8. class man{
 9. private:
10.     time_t dob;
11.     char name[100];
12. public:
13.     man(char* name){
14.         dob = time(0);
15.         strcpy(this->name, name);
16.     }
17. 
18.     void details(){
19.         printf("%s %d\n", name, dob);
20.     }
21. };
22. 
23. int main( int argc, char** argv){
24.     man * m1 = new man("douglas adams");
25.     man * m2 = new man("captain kirk");
26.     man * m3 = new man("michael schumi");
27. 
28.     TRandomAccess<man> manfile;
29. 
30.     manfile.Open("man_store");
31. 
32.     manfile.Write(m1);
33.     manfile.Write(m2);
34.     manfile.Write(m3);
35. 
36.     manfile.Close();
37.     
38.     manfile.Open("man_store");
39. 
40.     man * manout = (man*)malloc(sizeof(man));
41.     
42.     manfile.Read(manout, 1);
43.     manout->details();
44. 
45.     for(manfile.ResetReadNext(0);manfile.ReadNext(manout)==0;){
46.         manout->details();
47.     }
48. 
49.     man * m2r = new man("james T kirk");
50.     manfile.Write(m2r, 1);
51. 
52.     for(manfile.ResetReadNext(0);manfile.ReadNext(manout)==0;){
53.         manout->details();
54.     }
55. 
56.     manfile.Close();
57.     free(m1);free(m2);free(m3);free(m2r);
58. }
Hide line numbers

3 comments:

Naviya Nair said...

Very interesting and good Explanation
ASP NET Training
ASP NET Training
ASP NET Online Training
C-Sharp Training
Dot Net Training in Chennai
Online .Net Training


MVC Training
WCF Training
Web-API Training
LINQ Training
Entity Framework
Training

Dot Net Interview Questions

Andrew Son said...

Wonderful post!!Dot net framework use to concentrate on the software environment to give contrast to the hardware environment, this phenomenon is known as the common language runtime. The program written in dot net features like this CLR (common language runtime). This framework works and provides the services like security, memory management, and exception handling.Thank you..!!
Regards,
dot net course | dot net training

Melisa said...

I have read your post, it was good to read & I am getting some useful info's through your blog keep sharing...
PHP Training|PHP Institutes in Chennai