Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

File Size

Posted on 2001-06-15
15
Medium Priority
?
1,045 Views
Last Modified: 2013-11-20
Hey ppl,

In the below given code, I have already opened a file with pFile, then i open a second file with CFile local
and keep reading from the pFile object and writing the same data to CFile local. Basically i'm copying one file to another.

In the While loop used in the below code i want to compare the Total File size of pFile with the total data written to CFile local,and exit the loop as soon as both the values are equal i.e. when data has been completely copied from file1 to file2. But the while loop is not functioning as it should be, it comes to a premateur end.

I know i can use While(nRead>0) instead of what i have used, But i want to exit the loop by comparing the two values. But i can't figure out why it isn't working.

Any suggestions ?




///////// Code Begins ///////////


DWORD fsize;
DWORD total_written=0;
fsize=pFile->GetLength();

     CFile local(test_file_name,CFile::modeCreate|CFile::modeNoTruncate   |CFile::modeWrite |CFile::typeBinary );  
          local.SeekToEnd();

UINT nRead = pFile->Read(szBuff, 100);            
local.Write(&szBuff,nRead);
total_written=nRead;

while(total_written!=fsize)
{
nRead = pFile->Read(szBuff, 100);            
local.Write(&szBuff,nRead);
total_written+=nRead;
}          


/////////////////////////////////////////////


0
Comment
Question by:nitshv
  • 5
  • 3
  • 3
  • +3
15 Comments
 
LVL 30

Expert Comment

by:Axter
ID: 6197238
How is it not working?
How much is written?
How premature is it?

Please give exact results
0
 
LVL 30

Expert Comment

by:Axter
ID: 6197241
Please show all the relevent code.
You code does not show how pFile gets open, and what happens after it's open.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6197250
You're using an & in the Write function.
I don't think that belongs there, and that could be thrown your code off.
It should be the following:
local.Write(szBuff,nRead);

And NOT local.Write(&szBuff,nRead);

You have this twice in your code.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 3

Expert Comment

by:GlennDean
ID: 6197262
Try the minor modification to see if this works:

UINT nRead = pFile->Read(szBuff, 100);            
local.Write(szBuff,nRead);  //Note not using &szBuff
total_written=nRead;

while(total_written < fsize)
{
  nRead = pFile->Read(szBuff, 100);            
  local.Write(szBuff,nRead);
  total_written+=nRead;
}          


0
 
LVL 3

Expert Comment

by:GlennDean
ID: 6197313
It's unclear why it end prematurely, but one thing it could be is you're using test_file_name both as the file to transfer from and to.  I made test_file_name as "MyFile.exe" and then wrote the following code and it worked great.

DWORD fsize;
char szBuff[256];
DWORD total_written=0;
DWORD dwLocalSize = 0;
fsize=pFile->GetLength();

CFile local("temp.txt",CFile::modeCreate | CFile::modeWrite |CFile::typeBinary );  
local.SeekToEnd();

UINT nRead = pFile->Read(szBuff, 100);            
local.Write(szBuff,nRead);
total_written=nRead;

dwLocalSize = local.GetLength();
while(total_written!=fsize)
{
  nRead = pFile->Read(szBuff, 100);            
         
  local.Write(szBuff,nRead);
  total_written+=nRead;
  TRACE("\nnRead=%ld,total_written=%ld",nRead,total_written);
  ::Sleep(1);
}  
     
DWORD dwLocal = local.GetLength();
if (dwLocal!=fsize)
{
  local.Close();
  local.Open("temp.txt",CFile::modeNoTruncate |   CFile::modeWrite |CFile::typeBinary );  
  dwLocal = local.GetLength();
  ASSERT(dwLocal==fsize);  
}

  Give the above a shot,

      Glenn          



0
 

Expert Comment

by:SrinivasaRao
ID: 6197525
Hai,
  As axert pointed it out, its not necessary to send address of a pointer to the CFile::Write() function. And second point i am suggesting is, You are opening file as given below :
CFile local(test_file_name, CFile::modeCreate | CFile::modeNoTruncate|CFile::modeWrite |CFile::typeBinary
);

Please remove CFile::modeNoTruncate from the mode of opening. Because you keep this as an option, if the file "test_file_name" already exists your data will be appended. So both lengths can be get equalled at any moment. However, if file is not there your code should work properly by modifying
 local.Write(&sizeBuf, nRead) ;
to
 local.Write(sizeBuf, nRead) ;

Respond with result.
BSR
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6197781
Simpler than getting the source file length... just read the source file and when the return value is 0, you are finished:

CFile fSrc, fDst;

fSrc.Open( "MySource.txt", CFile::modeRead |CFile::shareDenyNone );

fDst.Open( "MyDest.txt", CFile::modeCreate |CFile::shareExclusive );

char szBuf[1024];
int nTotal= 0;
do {  
   int nActual= fSrc.Read( szBuf, sizeof(szBuf) );
   fDst.Write( szBuf, nActual );
   nTotal += nActual;
   TRACE("\nRead=%d,SoFar=%d",nRead,nTotal);
} while nActual != 0;

fSrc.Close();
fDst.Close();

Simpler is better
-- Dan
0
 

Author Comment

by:nitshv
ID: 6198041

Here is the complete code, what i'm basically doing is reading a CHttpFile from a server and copying it as a file on local machine.

Dan, the reason why i'm not using while(nActual!=0) is because i want to read the file in segments so that i can resume the file copying if connection to the server is lost, so in order to achieve that i need to know when my local file size reaches total file size so that i can stop the download process.


In the below given code, it works absolutely fine as long as the file size is less than 1MB but for file larger than 1 MB it produces errors during execution.


/////////////////////////////////////////////////////////

DWORD total_written=0;
DWORD fsize=1;

void CResumeDlg::OnCancel()
{
     
     CInternetSession session("My Session");
     CHttpConnection* pServer = NULL;
     CHttpFile* pFile = NULL;
     DWORD dwRet;


     try
     {
         
          CString strServerName;
     


          pServer = session.GetHttpConnection("localhost");

         
          CString test_file_name="test.exe";
         
     
          pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET, test_file_name);          
          pFile->SendRequest();
          if(pFile->QueryInfoStatusCode(dwRet)==0)
               AfxMessageBox("Fail");            
     
               
         
          if (dwRet == HTTP_STATUS_OK)
          {

               char szBuff[1024*20];
               fsize=pFile->GetLength();

               
               
               if(fsize==total_written)
               {

                    AfxMessageBox("done");
                    return;

               }    

               
             CFile local(test_file_name,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite |CFile::typeBinary );  
             
             
             pFile->Seek((long)total_written,CFile::begin);                
     
             UINT nRead = pFile->Read(szBuff, 1024*20);            

             local.SeekToEnd();
            local.Write(szBuff,nRead);    
             total_written+=nRead;

             local.Close();              
           
               
          }
         
       
          delete pFile;
          delete pServer;

         
     }


     catch (CInternetException* pEx)
     {
               
     }

     session.Close();
     
     OnCancel();
     

}



///////////////////////////////////////////////


0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6199437
>>but for file larger than 1 MB it produces errors during execution.

It would help to know what errors it produces.

As always, I suggest removing the try...catch handling so that you can see the actual errors.  Nobody ever does this though I can't imagine why...

I'd also use:

  LONG nNewPos= pFile->Seek((long) total_written,CFile::begin);                

and then I'd examine nNewPos to see if all is well.

>>the reason why i'm not using while(nActual!=0) is because i want to read the file in segments so that i can resume the file copying...

Think about it... you can still use while(nActual!=0) in any case.  When the return is 0, you have reached the end of the source file.

There are several other oddities in this last post:
1) Why are you doing this in an OnCb\ncel() handler?

2) Why is there no loop that will keep reading until the end of the file?  Your code just attempts to read 20K for the file, then ends.

3) Why are you opening with the with CFile::modeCreate when you know that the file already exists?

4) Why do you not check the return values of calls such as local.SeekToEnd() even though you know that errors are happening?

-- Dan
0
 

Author Comment

by:nitshv
ID: 6200500
Ok I have solved the problem, the error was coming due to stack overflow so i removed the recursion.

But now there's another problem that has come up. I'm unable to get the correct file size of the remote file.

I use the following code to get the file size and it gives me incorrect file size.



////////////////////////////////////


     CInternetSession session("My Session");
     CHttpConnection* pServer = NULL;
     CHttpFile* pFile = NULL;
     DWORD dwRet;


          CString strServerName;

          pServer = session.GetHttpConnection("localhost");

         
          CString test_file_name="/test.zip";
         
     
          pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET, test_file_name);          
          pFile->SendRequest();
          if(pFile->QueryInfoStatusCode(dwRet)==0)
               AfxMessageBox("Fail");            
     
     
               fsize=pFile->GetLength();
                 
               char buff[5];
                    sprintf(buff,"%d",fsize);
                    AfxMessageBox(buff);


///////////////////////////////////////////////////////////
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6201006
Web servers are not required to provide the length of a file.  That is why, when browsing, the IE progress guage is sometimes shown as empty.

You can eyeball the server response headers by using
  CString sRespHeadersRcvd;
  pFile->QueryInfo( HTTP_QUERY_RAW_HEADERS_CRLF, sRespHeadersRcvd );

and you might consider checking the return from QueryInfoStatusCode to see if the file was found.  You could also override the StatusCallback to learn the progress of the request.
=-=-=-=-=-=-=-=-=-=-=-=-
Call it beating a dead horse... but I have already stated that you don't need to know the length of the file in order to read all of it.

-- Dan
0
 

Author Comment

by:nitshv
ID: 6204388
Alrite Dan thanks for your help....i think i will stick to your method instead of getting the file size.

But Now, whom do i give points to ?

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6221822
-- Dan
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 400 total points
ID: 6307029
hi nitshv,
Do you have any additional questions?  Do any comments need clarification?

-- Dan
0
 
LVL 1

Expert Comment

by:Moondancer
ID: 6353591
Force accepted by moderator.  In the event Asker returns with additional needs related to this question, please respond and continue the collaboration process.
Thank you,
Moondancer
Community Support Moderator @ Experts Exchange
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
Ready to get certified? Check out some courses that help you prepare for third-party exams.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Want to learn how to record your desktop screen without having to use an outside camera. Click on this video and learn how to use the cool google extension called "Screencastify"! Step 1: Open a new google tab Step 2: Go to the left hand upper corn…

926 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question