Solved

File Size

Posted on 2001-06-15
15
1,032 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
 
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
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

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

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
GIF file bit manipulation for color change 5 104
Hibernate methods 2 58
ShiftLeft challenge 21 66
mapBully challenge 6 93
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
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.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

743 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now