Jump to content
  • Advertisement
Sign in to follow this  
MarlboroKing

Reading certain sizes from file buffer

This topic is 2500 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. I'm attempting to read a buffer, at a specific location and withdrawing only a certain size of data. However, I just get garbage at the beginning of my variable, (sometimes) following the needed data at the end of the file.

Here is where I open the file (including what's in the file at the top), grab the size and allocate my buffer:

/*
file data : 72775645645645658345345
*/

bool DFile::Open( const char* szFilename, DFILE_READMODE nMode )
{
ZeroMemory( &m_szFilename, sizeof(m_szFilename) );
m_nMode = DFILEREADMODE_UNKNOWN;
m_nSize = 0;

errno_t nRet = NULL;

switch( nMode )
{
case DFILEREADMODE_UNKNOWN:
{
return false;
}
case DFILEREADMODE_READ:
{
nRet = fopen_s( &m_pFile, szFilename, "r" );
break;
}
case DFILEREADMODE_WRITE:
{
nRet = fopen_s( &m_pFile, szFilename, "w" );
break;
}
case DFILEREADMODE_READWRITE:
{
nRet = fopen_s( &m_pFile, szFilename, "rw" );
break;
}
case DFILEREADMODE_BINARYREAD:
{
nRet = fopen_s( &m_pFile, szFilename, "rb" );
break;
}
case DFILEREADMODE_BINARYWRITE:
{
nRet = fopen_s( &m_pFile, szFilename, "wb" );
break;
}
case DFILEREADMODE_BINARYREADWRITE:
{
nRet = fopen_s( &m_pFile, szFilename, "rwb" );
}
case DFILEREADMODE_END:
{
return false;
}
default:
return false;
}

// TODO: Check nRet value.

if( /*nRet != .. || */ !m_pFile )
return false;

fseek( m_pFile, 0, SEEK_END );
m_nSize = m_nSaveSize = ftell( m_pFile );
rewind( m_pFile );

m_pData = (void*)malloc( m_nSize );
memset( m_pData, 0, m_nSize );
fread( m_pData, sizeof(char), m_nSize, m_pFile );

fseek( m_pFile, 0, SEEK_END );
m_nSize = ftell( m_pFile ); //m_nSize now equal 23
rewind( m_pFile );

m_nIndex = 0;

return true;
}


So far so good. Although, I did notice something strange with this when debugging.. I do see the data from the text file, but after it all, it's just plain garbage (I.E; 434123235??????????????????????????????????????????????? in the _base variable in the FILE structure)

Here, is where I read the data (Note; they all majorly look alike so I just included 2):

long DFile::ReadLong( int nIndex )
{
if( IsReadMode() || IsReadWriteMode() )
{
long nPlace = GetIndexValue( nIndex );
IncrIndexValue( nIndex, sizeof(long) );
return *(long*)( (BYTE*)m_pData + nPlace );
}

return 0;
}

char DFile::ReadChar( int nIndex )
{
if( IsReadMode() || IsReadWriteMode() )
{
long nPlace = GetIndexValue( nIndex );
IncrIndexValue( nIndex, sizeof(char) );
return *(char*)( (BYTE*)m_pData + nPlace );
}

return 0;
}


So, using this works just dandy:

.....
.....

DFile* pFile = new DFile();

if( !pFile->Open( "filetest.txt", DFILEREADMODE_READ ) )
DDebugPrint( "Error opening filetest.txt" );

char nType = pFile->ReadChar();

DGetMain()->Run( NULL );

return 0;
}


But, as soon as I switch off of char/uchar, I get garbage. My index is fine, it shows 0 at first, then gets increased by a value of sizeof(unsigned long). I just finished debugging.. again, and this is the result from using long:


....
....
DFile* pFile = new DFile();

if( !pFile->Open( "filetest.txt", DFILEREADMODE_READ ) )
DDebugPrint( "Error opening filetest.txt" );

long nType = pFile->ReadLong();
//After stepping over this line, nType now equals //926364215

DGetMain()->Run( NULL );

return 0;
}


Any ideas? Been frustrated over this for the past couple of days. :[

Share this post


Link to post
Share on other sites
Advertisement
...

Your file contains the STRING representation of the numbers.

You then ask for a long and cast it using magic pointers.

The result is the binary representation of the STRING of 4 numbers (sizeof(long) on your platform most likely). Or in hex: 0x37373237
which happen to be the characters '7', '7', '2', '7'. The digits are flipped because you're on a little endian system.

In ASCII the CHARACTER representations of the numeric literals start at 0x30 and proceed through 0x39...
that is:
The binary representation of '0' in hex is 0x30
The binary representation of '9' in hex is 0x39
The binary representation of '\0' in hex is 0x00
The binary representation of '\x09' in hex is 0x09


So far so good. Although, I did notice something strange with this when debugging.. I do see the data from the text file, but after it all, it's just plain garbage (I.E; 434123235??????????????????????????????????????????????? in the _base variable in the FILE structure)

C-strings are null terminated. Your file is not.



long DFile::ReadLong( int nIndex )
{
if( IsReadMode() || IsReadWriteMode() )
{
long nPlace = GetIndexValue( nIndex );
IncrIndexValue( nIndex, sizeof(long) );
return *(long*)( (BYTE*)m_pData + nPlace );
}

return 0;
}

char DFile::ReadChar( int nIndex )
{
if( IsReadMode() || IsReadWriteMode() )
{
long nPlace = GetIndexValue( nIndex );
IncrIndexValue( nIndex, sizeof(char) );
return *(char*)( (BYTE*)m_pData + nPlace );
}

return 0;
}


This is a terrible idea. your read/write flag should be just that, flags. Thus Read and Write should be OR compatible. Thus you should only require one check for if reading is supported, rather than checking if reading OR reading and writing OR reading and writing and is binary OR reading and writing and is big endian conversion capable and binary.



DFile* pFile = new DFile();

if( !pFile->Open( "filetest.txt", DFILEREADMODE_READ ) )
DDebugPrint( "Error opening filetest.txt" );

char nType = pFile->ReadChar();

DGetMain()->Run( NULL );

return 0;

What you new, you delete.

Share this post


Link to post
Share on other sites
926364215 is 0x37373237 which is '7277' (with byte order fixed due to endianness). That's exactly what is in the file according to the file data comment.

Why were you expecting something else?


Edit: Too slow...

Share this post


Link to post
Share on other sites

...

Your file contains the STRING representation of the numbers.

You then ask for a long and cast it using magic pointers.

The result is the binary representation of the STRING of 4 numbers (sizeof(long) on your platform most likely). Or in hex: 0x37373237
which happen to be the characters '7', '7', '2', '7'. The digits are flipped because you're on a little endian system.

In ASCII the CHARACTER representations of the numeric literals start at 0x30 and proceed through 0x39...
that is:
The binary representation of '0' in hex is 0x30
The binary representation of '9' in hex is 0x39
The binary representation of '\0' in hex is 0x00
The binary representation of '\x09' in hex is 0x09



I actually JUST realized that a few moments ago. (What can I say, 20-hour long day, following 4 hours of sleep gets to ya..) Obvious mistakes are never where you look at the first time.


[quote name='MarlboroKing' timestamp='1328729766' post='4911009']
So far so good. Although, I did notice something strange with this when debugging.. I do see the data from the text file, but after it all, it's just plain garbage (I.E; 434123235??????????????????????????????????????????????? in the _base variable in the FILE structure)

C-strings are null terminated. Your file is not.
[/Quote]

[s]Ahh, I see. So basically, just add an additional byte to my buffer and add the '\0' at the end.[/s] Ignore that, was thinking of my buffer when typing this out.
Gah, can't think today.


[quote name='MarlboroKing' timestamp='1328729766' post='4911009']
long DFile::ReadLong( int nIndex )
{
if( IsReadMode() || IsReadWriteMode() )
{
long nPlace = GetIndexValue( nIndex );
IncrIndexValue( nIndex, sizeof(long) );
return *(long*)( (BYTE*)m_pData + nPlace );
}

return 0;
}

char DFile::ReadChar( int nIndex )
{
if( IsReadMode() || IsReadWriteMode() )
{
long nPlace = GetIndexValue( nIndex );
IncrIndexValue( nIndex, sizeof(char) );
return *(char*)( (BYTE*)m_pData + nPlace );
}

return 0;
}


This is a terrible idea. your read/write flag should be just that, flags. Thus Read and Write should be OR compatible. Thus you should only require one check for if reading is supported, rather than checking if reading OR reading and writing OR reading and writing and is binary OR reading and writing and is big endian conversion capable and binary.
[/Quote]

Makes sense, fixing that right now. :]


What you new, you delete.


It's a test-phase for my engine, new/delete isn't important at the moment for this test. But I do know the horrors of not deleting/free'ing of what you allocate... A couple of computer restarts sure makes you start on that quite quickly.

Never really worked with files, most I've done is the simple fget, fprintf, etc. - just still can't believe I overlooked the hexadecimal numbers.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!