Solved

File Size

Posted on 2001-06-15
15
1,041 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Do you have a plan for Continuity?

It's inevitable. People leave organizations creating a gap in your service. That's where Percona comes in.

See how Pepper.com relies on Percona to:
-Manage their database
-Guarantee data safety and protection
-Provide database expertise that is available for any situation

 
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 100 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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
In this post we will learn different types of Android Layout and some basics of an Android App.
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.
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …
Suggested Courses

627 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