Thread: filesplitting program I wrote

  1. #1
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72

    filesplitting program I wrote

    Hello. I wrote this file splitting utility (and it works!!)

    It's for command line: Usage is -> splt [size in bytes] file

    I also wrote a join utility which joins all the parts to create the file again,
    which I would like to eventually incorporate into one utility that splits and joins.

    I'm basically looking for tips on how I can better organize it (functions, etc.)
    Also, for all the "if" statements checking for errors, is there a better way to
    do these error checks instead of multiple if -> fprintf statements?

    I also need some insight into organizing functions

    e.g

    the function 'getfilenameout' uses sprintf to build filename.000, filename.001. etc each
    time it's called and open_outfile calls this function to get the name of the next
    output file to create. Is this good design or should it all be done in one function?

    thanks

    Code:
    /* splt.c */
    /* splits file into user specified byte parts */
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <fcntl.h>
    #include <errno.h>
    
    #define BUFSIZE 4096
    
    char *getfilenameout(char *filenamebuf, char *filename, unsigned int suffix);
    FILE *open_outfile(char *filenamebuf, char *filename, unsigned int suffix);
    void display_usage(void);
    
    
    int main(int argc, char *argv[])
    {
    	FILE *fp, *outfp, *infout;
    	char buf[BUFSIZE];
    	char filenamebuf[100];
    	char *filenameout;
    	unsigned int size, parts;
    	unsigned int suffix = 0;
    	int i, c;
    	i = 0;
    	char *filename = argv[2];
    	struct stat fl;
    	struct stat *pt = &fl;
    	char *endptr = 0;
    
    	if (argc != 3) {
    		display_usage();
    		exit(1);
    	}
    
    	size = strtoul(argv[1], &endptr, 10);
    
    	if (*endptr != 0) {
    		fprintf(stderr, "splt: not a valid decimal number.\n");
    		exit(1);
    	}
    
    	if (size < 1) {
    		fprintf(stderr, "splt: size must be at least 1 byte.\n");
    		exit(1);
    	}
    
    	/* open file to splt */
    	if ( (fp = fopen(argv[2], "rb")) == NULL) {
    		fprintf(stderr, "splt: &#37;s: ", argv[2]);
    		perror("");
    		exit(1);
    	}
    
    
    	/* get file size */
    	stat(argv[2], pt);
    
    
    	/* make sure size of file / specified split size will fit into 1000 parts */
    	if ( (parts = pt->st_size / size) > 1000) {
    		fprintf(stderr, "splt: split would require greater than 1000 parts.\n");
    		exit(1);
    	}
    
    	/* save info on split to inf file (file.001) */
    	infout = open_outfile(filenamebuf, filename, suffix++);
    	fprintf(infout, "%s\n", argv[2]);
    
    	outfp = open_outfile(filenamebuf, filename, suffix++);
    	printf("creating %s\n", filenamebuf);
    	fprintf(infout, "%s\n", filenamebuf);
    
    
    	/* main splt loop */
    	while ( (c = fgetc(fp)) != EOF) {
    		if (i == size) {
    			fclose(outfp);
    			i = 0;
    			outfp = open_outfile(filenamebuf, filename, suffix++);
    			printf("creating %s\n", filenamebuf);
    			fprintf(infout, "%s\n", filenamebuf);
    		}
    		fputc(c, outfp);
    		i++;
    	}
    
    	fclose(fp);
    	fclose(outfp);
    	fclose(infout);
    
    	return 0;
    }
    char *getfilenameout(char *filenamebuf, char *filename, unsigned int suffix)
    {
    	sprintf(filenamebuf, "%s.%03d", filename, suffix);
    	return filenamebuf;
    }
    FILE *open_outfile(char *filenamebuf, char *filename, unsigned int suffix)
    {
    	char *filenameout;
    	FILE *outfp;
    
    	filenameout = getfilenameout(filenamebuf, filename, suffix);
    	outfp = fopen(filenameout, "wb");
    	return outfp;
    }
    void display_usage(void)
    {
    	fprintf(stderr, "Usage: splt [size in bytes] file.\n");
    }
    Last edited by movl0x1; 05-29-2007 at 11:21 AM.

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Looks like you're on UNIX. Why are you writing a program to do this? Use "split," it already exists.

  3. #3
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72
    Cause I like writing my own programs for practice



    Peace out
    Last edited by movl0x1; 05-29-2007 at 11:01 AM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Seems OK so far.

    > if ( (parts = pt->st_size / size) > 1000)
    You might want to think about this line.
    The .000 file is reserved (so there's only 999 others)
    You don't count the remainder (if pt->st_size &#37; size isn't 0, you need an extra file)


    > getfilenameout
    Would be better if the size of the destination were passed as well, and some attempt to determine if sprintf() would overflow the space or not.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Code:
    	struct stat fl;
    	struct stat *pt = &fl;
    ...
    	stat(argv[2], pt);
    
    
    	/* make sure size of file / specified split size will fit into 1000 parts */
    	if ( (parts = pt->st_size / size) > 1000) {
    There's no need for the pt pointer. Just pass &fl to stat(), and in your if() condition use fl.st_size.

    The way you're doing it isn't wrong, but it just adds an unnecessary layer of obscurity IMO.
    Last edited by itsme86; 05-29-2007 at 11:57 AM.
    If you understand what you're doing, you're not learning anything.

  6. #6
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72
    Thanks guys!!

    Yes, I know I need error checks in sprinf , etc. Just did this
    quicky and will re-write it.

    Thanks salem. Forgot that that only leaves 999 after the .000 is
    used.

    Thanks itsme86. Yes, since it will always point to the struct
    I guess your right, just pass a constant (&fl).
    Last edited by movl0x1; 05-29-2007 at 11:35 AM.

  7. #7
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    size = strtoul(argv[1], &endptr, 10);
    I'm pretty sure that strtoul() is in <string.h>, which you haven't included.

    Code:
    #define BUFSIZE 4096
    char buf[BUFSIZE];
    That's confusing . . . there's a constant called BUFSIZ in <stdio.h> which is probably pretty much what you want. If it isn't, consider changing the name. Actually, looking at your code again, I don't think buf is used anywhere. I might be missing something.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by dwks View Post
    Code:
    size = strtoul(argv[1], &endptr, 10);
    I'm pretty sure that strtoul() is in <string.h>, which you haven't included.
    It's in stdlib.h.

    I hate it. memcpy() seems like a "stdlib-ish" kind of function and yet it's in string.h. strtoul seems like a "string-ish" kind of function and yet it's in stdlib.h. The world is messed, I tell you.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can someome help me with a program please?
    By WinterInChicago in forum C++ Programming
    Replies: 3
    Last Post: 09-21-2006, 10:58 PM
  2. Replies: 2
    Last Post: 04-25-2005, 11:59 AM
  3. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  4. wrote a program; please review/comment
    By spirited in forum C++ Programming
    Replies: 4
    Last Post: 05-22-2003, 01:37 PM
  5. My program, anyhelp
    By @licomb in forum C Programming
    Replies: 14
    Last Post: 08-14-2001, 10:04 PM