1 /*
2 * Modification History
3 *
4 * 2001-February-11 Jason Rohrer
5 * Created.
6 *
7 * 2001-April-12 Jason Rohrer
8 * Changed so that File is not destroyed when this stream is destroyed.
9 *
10 * 2001-April-29 Jason Rohrer
11 * Fixed a bug in the use of fwrite
12 * (num elements and element size swapped).
13 * Fixed a memory leak in the error message handling.
14 *
15 * 2006-August-22 Jason Rohrer
16 * Fixed include order bug.
17 */
18
19 #include "minorGems/common.h"
20
21
22 #include "File.h"
23
24
25 #ifndef FILE_OUTPUT_STREAM_CLASS_INCLUDED
26 #define FILE_OUTPUT_STREAM_CLASS_INCLUDED
27
28 #include "minorGems/io/OutputStream.h"
29
30 #include <stdio.h>
31
32 /**
33 * File implementation of an OutputStream.
34 *
35 * @author Jason Rohrer
36 */
37 class FileOutputStream : public OutputStream {
38
39 public:
40
41 /**
42 * Constructs an output stream.
43 *
44 * @param inFile the file to open for writing.
45 * If the file does not exist, it will be created.
46 * inFile is NOT destroyed when this class is destroyed.
47 * @param inAppend set to true to append to file. If
48 * file does not exist, file is still created. Defaults
49 * to false.
50 */
51 FileOutputStream( File *inFile, char inAppend = false );
52
53
54 /**
55 * Destroys this stream and closes the file.
56 */
57 ~FileOutputStream();
58
59
60 /**
61 * Gets the file attached to this stream.
62 *
63 * @return the file used by this stream.
64 * Should not be modified or destroyed by caller until after
65 * this class is destroyed.
66 */
67 File *getFile();
68
69
70 // implementst OutputStream interface
71 virtual long write( unsigned char *inBuffer, long inNumBytes );
72
73 private:
74 File *mFile;
75
76 FILE *mUnderlyingFile;
77 };
78
79
80
81
FileOutputStream(File * inFile,char inAppend)82 inline FileOutputStream::FileOutputStream( File *inFile,
83 char inAppend )
84 : mFile( inFile ) {
85
86 int fileNameLength;
87
88 char *fileName = mFile->getFullFileName( &fileNameLength );
89
90 if( inAppend ) {
91 mUnderlyingFile = fopen( fileName, "ab" );
92 }
93 else {
94 mUnderlyingFile = fopen( fileName, "wb" );
95 }
96
97 if( mUnderlyingFile == NULL ) {
98 // file open failed.
99
100 char *stringBuffer = new char[ fileNameLength + 50 ];
101 sprintf( stringBuffer, "Opening file %s failed.", fileName );
102 setNewLastError( stringBuffer );
103 }
104
105 delete [] fileName;
106 }
107
108
109
~FileOutputStream()110 inline FileOutputStream::~FileOutputStream() {
111 if( mUnderlyingFile != NULL ) {
112 fclose( mUnderlyingFile );
113 }
114 }
115
116
117
getFile()118 inline File *FileOutputStream::getFile() {
119 return mFile;
120 }
121
122
123
write(unsigned char * inBuffer,long inNumBytes)124 inline long FileOutputStream::write(
125 unsigned char *inBuffer, long inNumBytes ) {
126
127 if( mUnderlyingFile != NULL ) {
128
129 long numWritten =
130 fwrite( inBuffer, 1, inNumBytes, mUnderlyingFile );
131
132 if( numWritten < inNumBytes ) {
133 int fileNameLength;
134 char *fileName = mFile->getFullFileName( &fileNameLength );
135
136 // some other kind of error occured
137 char *stringBuffer = new char[ fileNameLength + 50 ];
138 sprintf( stringBuffer, "Writing to file %s failed.",
139 fileName );
140 setNewLastError( stringBuffer );
141
142 delete [] fileName;
143
144 if( numWritten == 0 ) {
145 // a complete write failure
146 return -1;
147 }
148 }
149
150 return numWritten;
151 }
152 else {
153 // file was not opened properly
154
155 int fileNameLength;
156 char *fileName = mFile->getFullFileName( &fileNameLength );
157 char *stringBuffer = new char[ fileNameLength + 50 ];
158 sprintf( stringBuffer,
159 "File %s was not opened properly before writing.",
160 fileName );
161 setNewLastError( stringBuffer );
162
163 return -1;
164 }
165 }
166
167
168
169 #endif
170