Board index » cppbuilder » Re: TFileStream Code

Re: TFileStream Code


2006-04-05 01:22:34 PM
cppbuilder23
"Maurice Anderson" < XXXX@XXXXX.COM >wrote in message
Quote
I am trying to write some code to create files greater than
the 2 Gig limit of TFileStream.
Unless you are using BCB 6 or BDS 2006, then TFileStream does not support
sizes greater than 2GB at all. You will have to work at the Win32 API level
for that, using CreateFile(), SetFilePosition(), and Read/WriteFile()
directly.
Which version of BCB are you actually using?
Quote
I get compiler error: Cannot create instance of Abstract class 'TStream'
The only way to get that error is if your descendant class is not overriding
all of TStream's abstract methods, thus making your own class abstract as
well, and not able to be instantiated directly. Please show your actual
code.
Quote
Problem is I pass a TFileStream variable(FS) to a number of functions
in my application for processing of it's buffer.
Your custom class is not an actual TFileStream at all, so you won't be able
to pass it around wherever TFileStream is expected.
Quote
So I am hoping to replace the TFileStream variable with my
TSmStream version that handles files greater than 2 Gigs.
That is fine, if you don't mind re-writing all of your other code that
depends on being passed TFileStream specifically.
Quote
bool __fastcall ReadBuffer(void * dest, const DWORD size);
bool __fastcall WriteBuffer(void * const src, const DWORD size);
bool __fastcall Seek (const unsigned __int64 delta, const DWORD
direction);
You are not overriding the abstract Read() and Write() methods of TStream at
all. That is why your class is abstract. Also, you are declaring your own
ReadBuffer() and WriteBuffer() methods when TStream already has those
methods publically available, and your Seek() method is hiding the virtual
Seek() method in TStream because your parameters do not match.
Quote
__published:
__property unsigned __int64 Size = {read=getFileSize,
write=setFileSize};
__property unsigned __int64 Position = {read=GetFilePosition,
write=SetFilePosition};
TStream already has its own Size and Position properties. You cannot
declare you own without interfering with those.
Since your code is not trying to use TStream properly, not even close, then
I suggest you not derive from TStream at all. Make your class be a
standalone class with no ancestor classes. Then you can do whatever you
want with it.
Quote
return CreateFile(path,
GENERIC_READ | GENERIC_WRITE,
0, //do not share FILE_SHARE_READ | FILE_SHARE_WRITE
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
Your class provides random access to the file handle. You should not be
specifying FILE_FLAG_SEQUENTIAL_SCAN. Also, you should always provide at
least FILE_SHARE_READ access. It is friendlier to the OS.
Gambit
 
 

Re:Re: TFileStream Code

Hello,
I am trying to write some code to create files greater than the 2 Gig limit
of TFileStream. I tried to use some code from deja by Remy at:
groups.google.com/group/borland.public.cppbuilder.language/browse_thread/thread/72a9a073c9e68af6/4ba9c2acf4b1d5b8
When I tried instantiating it in my CPP:
FileName = "c:\newFile.txt";
TSmStream *FS = new TSmStream(FileName);
TSmStream *FS->Size = SomeSize;
I get compiler error: Cannot create instance of Abstract class 'TStream'
Problem is I pass a TFileStream variable(FS) to a number of functions in my
application for processing of it's buffer. So I am hoping to replace the
TFileStream variable with my TSmStream version that handles files greater
than 2 Gigs.
Here is what I did:
H File
//---------------------------------------------------------------------------
#ifndef TSmStreamH
#define TSmStreamH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TSmStream : public TStream
{
private:
HANDLE __hdl;
unsigned __int64 __fastcall getFileSize(void);
void __fastcall setFileSize(unsigned __int64 Ssize);
unsigned __int64 __fastcall GetFilePosition (void);
void __fastcall SetFilePosition(unsigned __int64 delta);
HANDLE __fastcall InitializeHandle (char* path);
protected:
public:
__fastcall TSmStream(char* path);
__fastcall ~TSmStream();
bool __fastcall ReadBuffer(void * dest, const DWORD size);
bool __fastcall WriteBuffer(void * const src, const DWORD size);
bool __fastcall Seek (const unsigned __int64 delta, const DWORD
direction);
bool __fastcall isValid(void);
__published:
__property unsigned __int64 Size = {read=getFileSize,
write=setFileSize};
__property unsigned __int64 Position = {read=GetFilePosition,
write=SetFilePosition};
};
//---------------------------------------------------------------------------
#endif
CPP File
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "TSmStream.h"
//---------------------------------------------------------------------------
__fastcall TSmStream::TSmStream(char* path)
: __hdl(INVALID_HANDLE_VALUE)
{
__hdl = InitializeHandle(path);
}
__fastcall TSmStream::~TSmStream()
{
if ( __hdl != INVALID_HANDLE_VALUE )
CloseHandle(__hdl);
}
unsigned __int64 __fastcall TSmStream::getFileSize(void)
{
ULARGE_INTEGER ul = {0};
ul.LowPart = GetFileSize(__hdl, &ul.HighPart);
if(ul.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
{
// the caller should use GetLastError() to test for error
return 0xFFFFFFFFFFFFFFFF;
}
return (unsigned __int64)ul.QuadPart;
}
void __fastcall TSmStream::setFileSize(unsigned __int64 Ssize)
{
Size = Ssize;
}
unsigned __int64 __fastcall TSmStream::GetFilePosition (void)
{
LARGE_INTEGER ul = {0};
ul.LowPart = SetFilePointer(__hdl, 0, &ul.HighPart, FILE_CURRENT);
if(ul.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
{
// the caller should use GetLastError() to test for error
return 0xFFFFFFFFFFFFFFFF;
}
return (unsigned __int64)ul.QuadPart;
}
void __fastcall TSmStream::SetFilePosition(unsigned __int64 delta)
{
Seek(delta, FILE_BEGIN);
}
HANDLE __fastcall TSmStream::InitializeHandle (char* path)
{
if ( !path ) return INVALID_HANDLE_VALUE;
return CreateFile(path,
GENERIC_READ | GENERIC_WRITE,
0, //do not share FILE_SHARE_READ | FILE_SHARE_WRITE
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
}
bool __fastcall TSmStream::ReadBuffer(void * dest, const DWORD size)
{
DWORD nNumberOfBytesRead = 0;
BOOL result = ReadFile(__hdl, dest, size, &nNumberOfBytesRead,NULL);
return (result && (size == nNumberOfBytesRead));
}
bool __fastcall TSmStream::WriteBuffer(void * const src, const DWORD size)
{
DWORD nNumberOfBytesWritten = 0;
BOOL result = WriteFile(__hdl, src, size, &nNumberOfBytesWritten, NULL);
return (result && (size == nNumberOfBytesWritten));
}
bool __fastcall TSmStream::Seek (const unsigned __int64 delta, const DWORD
direction)
{
// DIRECTION
// FILE_BEGIN The starting point is zero or the beginning of the file.
// FILE_CURRENT The starting point is the current value of the file
pointer.
// FILE_END The starting point is the current end-of-file position.
ULARGE_INTEGER ul = {0};
ul.QuadPart = delta;
// DWORD result = SetFilePointer(__hdl, ul.LowPart, &ul.HighPart,
direction);
DWORD result = SetFilePointer(__hdl, ul.LowPart, (long*)&ul.HighPart,
direction);
if(result == 0xFFFFFFFF && GetLastError() != NOERROR)
return false;
return true;
}
bool __fastcall TSmStream::isValid(void)
{
return ( __hdl != INVALID_HANDLE_VALUE);
}