hypheni
hypheni

Reputation: 816

CFile read data to buffer

I'm trying to get all the bytes from a file to read on a BYTE* variable. I'm trying to read a whole xml file data into memory which looks like:

<?xml version="1.0" encoding="utf-8"?>
<DataBlock xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Device>3867242</Device>
    <Manufacturer>COMPANY LTD</Manufacturer>
    <Data>15</Data>
    <VendorID>00-291-647</VendorID>
    <TimeStamp>2014-08-13 12:40:11</TimeStamp>
</DataBlock>

But ending up with reading something like:

"<?xml version="1.0" encoding="utf-8"?>
<DataBlock xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Device>3867242</Device>
    <Manufacturer>COMPANY LTD</Manufacturer>
    <Data>15</Data>
    <VendorID>00-291-647</VendorID>
    <TimeStamp>2014-08-13 12:40:11</TimeStamp>
</DataBlock>ýýýý««««««««þ"

Below is the code to read it..

CFile oFile;
if(oFile.Open(filePath, CFile::modeRead) == FALSE)
  return NULL;

long iFileSiz = oFile.GetLength();
BYTE* pData = new BYTE[iFileSiz];

oFile.Read(pData, iFileSiz);
oFile.Close();

I'm getting some garbage character at the end of buffer or some files couldn't be read completely.

Output is captured from Visual studio debugger.

Upvotes: 3

Views: 11350

Answers (3)

affen&#228;rschle
affen&#228;rschle

Reputation: 135

common error, since you have to declare the array 1 byte longer than the needed to have space for the terminating NULL:

BYTE* pData = new BYTE[iFileSiz + 1];

pData[ iFileSiz] = 0;

Upvotes: 1

Himanshu
Himanshu

Reputation: 4395

Post is old but I wouls like to add an answer to it, so that it will be helpful for other users in future.

CFile oFile;
if(oFile.Open(filePath, CFile::modeRead) == FALSE)
  return NULL;

long iFileSiz = oFile.GetLength();  // Getting is the content length
BYTE* pData = new BYTE[iFileSiz];

oFile.Read(pData, iFileSiz);       //  Reading file content

pData[iFileSiz] = '\0';            //  Add last character as NULL

oFile.Close();

Now it will display the exact output as in file.

Upvotes: 1

Andrew Komiagin
Andrew Komiagin

Reputation: 6556

I don't see any problems with your code. However, I would use CByteArray instead of raw BYTE*. The following example can be used if you need to read data from binary files:

CFile oFile;
if(!oFile.Open(filePath, CFile::modeRead))
  return;

CByteArray fileData;
fileData.SetSize(oFile.GetLength()); 
UINT bytesRead = oFile.Read(fileData.GetData(), fileData.GetSize());
oFile.Close();

If you work with text files (need to NULL terminate the data read):

ULONGLONG dwLength = oFile.GetLength();

if (dwLength == 0)
    return FALSE;

int nSize = (int)dwLength + 1;
CStringA sData;

try
{
    LPSTR pBuffer = sData.GetBuffer(nSize);
    oFile.Read(pBuffer, nSize);
    pBuffer[(int)dwLength] = NULL;
    sData.ReleaseBuffer();
}
catch(CFileException* pFileException)
{
    pFileException->Delete();
    return;
}
catch(CMemoryException* pMemoryException)
{
    pMemoryException->Delete();
    return;
}
catch(...)
{
    return;
}

IMPORTANT: This approach is good enough for small files. Please note that it is better to read and process huge files chunk by chunk to prevent memory allocation issues.

Upvotes: 5

Related Questions