LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-27-2005, 07:19 AM   #1
climbingmerlin
Member
 
Registered: Mar 2004
Location: UK
Distribution: Fedora, OpenSuse
Posts: 91

Rep: Reputation: 15
copying files(s) in c


I have another programming question, whilst I learn C. I am trying to copy a file from one location to another in binary, as I do not know what 'type' of file it is. I have written the following function, that when trying to write to file, i get a segmentation fault.

Code:
void doc_to_workspace(char* filename,char* workspacefile)
{
  int *fpw;
  int *fpr;
  FILE *filew;
  FILE *filer;
  
  /*Open files for copying*/
  if((fpw = fopen(workspacefile,"wb")) == NULL){
    fprintf(stderr,"Can not copy file to workspace - File write Error\n");
  }
  if((fpr = fopen(filename,"rb"))==NULL){
    fprintf(stderr,"Can not copy file to workspace = File read Error\n");
  }
  
  /*Read file by 1MB chunks and write to workspace location*/
  int len =0;
  while((len = fread(FILEBUF,1,sizeof(FILEBUF),filer))>0){
    fwrite(FILEBUF,1,len,filew);
  }
  
  /*close file connections*/
  fclose(filer);
  fclose(filew);
}
Any ideas on where I am going wrong with this, I have to confess I am not 100% sure what I am doing so it has been a bit of trial and error. Just to note FILEBUF = 1048576.

Any help with this or generally with my C programming style etc, is gratefully received.

Thanks....
 
Old 10-27-2005, 09:07 AM   #2
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Re: copying files(s) in c

Quote:
Originally posted by climbingmerlin
I am trying to copy a file from one location to another in binary, as I do not know what 'type' of file it is.
In UNIX/Linux there's no difference at all between "binary" and "text" files. The mode option "b" or "t" is only there for compatability with OS's that do handle text and binary differently.

Fixed your code (but didn't test it). Changes in red.

Code:
#include <stdio.h>
/*  ...  */

void doc_to_workspace(char* filename,char* workspacefile)
{
/* int *fpw;   // remove */
/* int *fpr;  // remove */
  FILE *filew;
  FILE *filer;
  
  /*Open files for copying*/
  if((filew = fopen(workspacefile,"wb")) == NULL){
    fprintf(stderr,"Can not copy file to workspace - File write Error\n");
  }
  if((filer = fopen(filename,"rb"))==NULL){
    fprintf(stderr,"Can not copy file to workspace = File read Error\n");
  }
  
  /*Read file by 1MB chunks and write to workspace location*/
  int len =0;
  while((len = fread(FILEBUF, sizeof(FILEBUF), 1,filer))>0){
    fwrite(FILEBUF, len, 1,filew);
  }
  
  /*close file connections*/
  fclose(filer);
  fclose(filew);
}
 
Old 10-27-2005, 09:35 AM   #3
climbingmerlin
Member
 
Registered: Mar 2004
Location: UK
Distribution: Fedora, OpenSuse
Posts: 91

Original Poster
Rep: Reputation: 15
Thanks for your reply... I have changed the code a little, it reads the file and writes it to the new location, however it loops constantly... didn't realise it till a 20K file took up almost 800MB!!! The problem is that it is not finding the end of the file.

Any ideas on how I can do that? Here is my reworked code.

Code:
void doc_to_workspace(char* filename,char* workspacefile)
{
  FILE *filew;
  FILE *filer;
  char buf[FILEBUF];
  /*char buf[1024];*/
  
  /*Open files for copying*/
  if((filew = fopen(workspacefile,"wb")) == NULL){
    fprintf(stderr,"Can not copy file to workspace - File write Error\n");
  }
  if((filer = fopen(filename,"rb"))==NULL){
    fprintf(stderr,"Can not copy file to workspace = File read Error\n");
  }
  
  /*Read file by 1MB chunks and write to workspace location*/
  /*int len =0;*/
  while((fread(&buf,sizeof(buf),1,filer)) !=feof){
    fwrite(&buf,sizeof(buf),1,filew);
  }
  
  /*close file connections*/
  fclose(filer);
  fclose(filew);
}
Again any help will be gratefully received... I am starting to gain a lot of respect for C programmers!
 
Old 10-27-2005, 10:21 AM   #4
climbingmerlin
Member
 
Registered: Mar 2004
Location: UK
Distribution: Fedora, OpenSuse
Posts: 91

Original Poster
Rep: Reputation: 15
One thing that I forgot to point out that, the size of file(s) that I am copying range from 40K to 20GB....
 
Old 10-27-2005, 10:38 AM   #5
naf
Member
 
Registered: Oct 2005
Location: Chicago, USA
Distribution: Slackware & Fedora
Posts: 66

Rep: Reputation: 15
First off, you didn't read Hko's entire code.

First mistake: You are not reading the right count in fread.
Second, the function feof is a function address!! So comparing a size_t to void * is syntactically correct C but semantically wrong. To use feof correctly, you pass it the file pointer feof( FILE *fptr );

Having a local variable of 1MB is fairly large to place on the stack! Consider making it either static (so that is not on the stack), use a global variable (so that is in the data segment), or dynamically allocate the buffer (heap). Of those, the dynamic allocation is the most error prone but the best memory usage in that you are not permaneantly reserving a megabyte of memory but rather asking the OS for dynamically allocated memory temporarily.

You should change your code like:

Code:
void doc_to_workspace(char* filename,char* workspacefile)
{
  FILE *filew;
  FILE *filer;
  char *buffer;
  size_t count;  /* Using size_t makes robust C code that is portable and avoids implicit type conversions. */
  
  /*Open files for copying*/
  if( ! ( buffer = (char *)malloc( sizeof( char ) * FILEBUF ) )  ) {
    fprintf(stderr,"Can not allocate memory for workspace - Memory allocation Error\n");
  }
  else if((filew = fopen(workspacefile,"wb")) == NULL){
    free( buffer ); /* Cleanup! */
    fprintf(stderr,"Can not copy file to workspace - File write Error\n");
  }
  else if((filer = fopen(filename,"rb")) == NULL){
    fclose( filew ); /* Cleanup! */
    free( buffer ); /* Cleanup! */
    fprintf(stderr,"Can not copy file to workspace = File read Error\n");
  }
  else
  {  
    /* Read file by FILEBUF sized chunks and write to workspace location. */
    /* If less than FILEBUF characters read, then no problem, write the partial out.  */
    /* If 0 bytes read, then consider the copy operation done.  If this is a device, then this should be changed. */
    while( ( count = fread( buffer, sizeof( char ), FILEBUF, filer ) ) > 0 )
      if( fwrite( buffer, sizeof( char ), count, filew ) != count ) 
        break; /* Error, could not write the full length. */
  
    /*close file connections*/
    fclose(filer);
    fclose(filew);

    free( buffer ); /* Cleanup! */
  }
}

Last edited by naf; 10-27-2005 at 10:40 AM.
 
Old 10-27-2005, 11:11 AM   #6
climbingmerlin
Member
 
Registered: Mar 2004
Location: UK
Distribution: Fedora, OpenSuse
Posts: 91

Original Poster
Rep: Reputation: 15
To both Hko and naf thanks.... I now have a working function that copies files

Can you suggest other ways of understanding memory management as, I am not sure if it is me but I do find the use of malloc() calloc() and the use of pointers rather confusing. I am finding C enjoyable but at the same time a frustrating lanaguage to learn!

If anyone has any tips to give at improving my C code, as I know it is messy and probably not following any coding standards, I would again be extremely grateful.
 
Old 10-27-2005, 11:36 AM   #7
naf
Member
 
Registered: Oct 2005
Location: Chicago, USA
Distribution: Slackware & Fedora
Posts: 66

Rep: Reputation: 15
I usually like going with the authors of the language:

The C Programming Language, 2nd Edition
Brian W. Kernighan, Dennis M. Ritchie
ISBN 0131103628

The C++ Programming Language
Bjarne Stroustrup
ISBN 0201889544


For UNIX like programming, I like the book by the late Stevens:

Advanced Programming in the UNIX Environment, 2nd Edition
W. Richards Stevens
ISBN 0201433079


There are plenty of good online tutorials too if you don't want to spend money.
Learn the glib memory management for some interesting insights.
http://developer.gnome.org/doc/API/2.0/glib/index.html
 
Old 10-27-2005, 03:00 PM   #8
Orkie
Member
 
Registered: Mar 2005
Distribution: Breezy Badger
Posts: 248

Rep: Reputation: 30
I don't think your style is bad. You squash the code up more than I do but that depends on the person writing it -- everybody does it differently. You also know how to comment too.
I've seen much, much worse on these forums.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Copying files paddyjoy Linux - Newbie 10 10-25-2013 12:12 PM
need help with copying files Earl Parker II Linux - General 8 09-12-2005 09:54 AM
copying files neozero62 Linux - Newbie 1 11-23-2003 06:38 PM
copying files Sol0 Linux - Software 7 08-18-2003 11:40 AM
Copying Files... viperquest Linux - Software 3 03-07-2003 03:41 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:18 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration