Προς το περιεχόμενο

Tεμαχισμός αρχείου σε C


profitis

Προτεινόμενες αναρτήσεις

Kαλησπέρα σε όλους και χρόνια πολλα...

 

Θέλω να γράψω ενα προγραμμάτακι στην C που θα στέλνω ένα αρχείο μέσω network...(σε περιβάλλον linux)

 

Για να γίνει όμως αυτο πρέπει να το τεμαχίζω σε κομμάτια των 300 bytes και το header του πακέτου πρέπει να ειναι της μορφής <αριθμός πακέτου,μέγεθος πακέτου> (αυτο μας δίνεται απο την εκφώνηση οπότε προφανώς πρέπει να το υλοποιήσουμε εμείς και δεν ειναι κάτι που γίνεται αυτόματα απο τα sockets,σωστα;)

 

Αρα αυτο ο ποιητής εννοεί οτι πρέπει να το κάνουμε εμεις...Δηλαδή όταν γίνεται το receive θα πρέπει να ερμηνεύουμε τον header και να τον επεξεργαζόμαστε ανάλογα αυτον και το πακέτο να το τοποθετούμε στο σωστό σημειο;

 

Επίσης ο τεμαχισμός πως ακριβώς μπορεί να γίνει;Με την fseek() δεν μετακινούμε τον δείκτη σε ένα αρχείο;

 

Ευχαριστώ εκ των προτέρων!!!

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Kαλησπέρα σε όλους και χρόνια πολλα...

 

Θέλω να γράψω ενα προγραμμάτακι στην C που θα στέλνω ένα αρχείο μέσω network...(σε περιβάλλον linux)

 

Για να γίνει όμως αυτο πρέπει να το τεμαχίζω σε κομμάτια των 300 bytes και το header του πακέτου πρέπει να ειναι της μορφής <αριθμός πακέτου,μέγεθος πακέτου> (αυτο μας δίνεται απο την εκφώνηση οπότε προφανώς πρέπει να το υλοποιήσουμε εμείς και δεν ειναι κάτι που γίνεται αυτόματα απο τα sockets,σωστα;)

 

Αρα αυτο ο ποιητής εννοεί οτι πρέπει να το κάνουμε εμεις...Δηλαδή όταν γίνεται το receive θα πρέπει να ερμηνεύουμε τον header και να τον επεξεργαζόμαστε ανάλογα αυτον και το πακέτο να το τοποθετούμε στο σωστό σημειο;

 

Επίσης ο τεμαχισμός πως ακριβώς μπορεί να γίνει;Με την fseek() δεν μετακινούμε τον δείκτη σε ένα αρχείο;

 

Ευχαριστώ εκ των προτέρων!!!

 

An xrisimopoieis to protokolo tcp tote dn thes tpt kai apla stelneis data me thn seira pou

to diavazeis.Kalo einai na matheis to theoritiko meros kai meta na ftiaxeis programma.An thes na stileis to arxeio me udp tote h diadikasia ginete ligo polyplokh afou to protokolo dn einai ftiagmeno gia teties doulies.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Καταρχήν, ο τεμαχισμός ενός αρχείου σε κομμάτια (split) μπορεί να γίνει με μια πολύ απλή (αλλά όχι και τόσο γρήγορη μέθοδο) σειριακή ανάγνωση του stream που μας ενδιαφέρει μέχρι να φτάσουμε στον απαιτούμενο αριθμό bytes που πρέπει να περιλαμβάνει το πακέτο μας ή στο τέλος-του-αρχείου δηλαδή στο EOF, ότι έρθει πιο γρήγορα.

 

Ένα πονηρό σημείο που πρέπει να έχουμε υπόψη μας είναι πως το τελευταίο πακέτο ενδέχεται να έχει διαφορετικό μέγεθος από αυτό που ζητάμε, δηλαδή ενδεχομένως να μην είναι 300bytes καθώς κανένας δεν μας εγγυάται εκ των προτέρων το συνολικό μέγεθος του αρχείου μας.

 

Η παρακάτω ρουτίνα _makePacket διαβάζει από την τελευταία θέση (τελευταίο offset –οπότε δεν χρειάζεσαι την fseek) του fStream, nSize bytes και αποθηκεύει τον αύξοντα αριθμό του νέου πακέτου στο pnHeaderCount. Η ρουτίνα επιστρέφει μια δομή _TPacket που περιλαμβάνει, τα δεδομένα που διάβασε από το fStream (_TPacket.Data), το μέγεθος τους (_TPacket.Len) που εκτός του τελευταίου πακέτου θα πρέπει να είναι πάντα _TPacket.Len==nSize και τον άυξωντα αριθμό του νέου πακέτου (_TPacket.Count) –το πρώτο πακέτο έχει αύξων αριθμό μηδέν, αν διαφωνείς και θες να έχει 1 άλλαξε το (int)(*(int*)pnHeaderCount)++; σε (int)++(*(int*)pnHeaderCount);

 

Αξίζει να σημειωθεί πως η _makePacket επιστρέφει σε περίπτωση αποτυχίας NULL σε συνδυασμό με μια επεξηγηματική αρνητική τιμή στο pnHeaderCount, έτσι pnHeaderCount==-1 => πως το fStream ήταν invalid (NULL ή EOF), -2 => πως υπήρξε πρόβλημα στην δέσμευση μνήμης για το _TPacket.Data member και -3 => πως ομοίως υπήρξε πρόβλημα στην δέσμευση μνήμης για την δομή _TPacket.

 

Τέλος, για να είμαστε σίγουροι πως ο κώδικας σπάζει το fStream σωστά, στην main, αναδομώ (συνενώνω) κάθε _TPacket που επιστρέφει η _makePacket με την βοήθεια της fwrite ως αρχείο ορισθέν στο argv[2]. Ύστερα μπορείτε εύκολα με την βοήθεια της console εντολής των MS-Windows fc να κάνετε compare τα αρχεία (argv[1]=source argv[2]=rebuilted-from-packages-file) για τυχόν διαφορές (αν υπάρχουν η ρουτίνα απέτυχε -Bug).

 

Ο κώδικας έχει γραφθεί σε CodeGear/Borland C/C++ Builder ως ANSI-C template και δοκιμάσθηκε σε αρχείο από 1byte ως 23MB.

 

Η ρουτίνα είναι αρκετά γενική και ελπίζω πως θα σου δώσει κάποια ιδέα του τι χρειάζεσαι, τώρα περί, Sockets κτλ. δεν υπεισέρχομαι καθώς όταν τα χρειάζομαι βασίζομαι σε έτοιμες βιβλιοθήκες (VCL/Indy κ.α.).

 

>
/*-Simple File-Split by Directx----------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
#ifdef __BORLANDC__
   #pragma hdrstop
#endif

/*---------------------------------------------------------------------------*/
typedef struct
{
   int Count, Len;
   unsigned char *Data;
}_TPacket;

_TPacket *_makePacket(FILE*,int nSize,int *pnHeaderCount);

#ifdef __BORLANDC__
   #pragma argsused
#endif
int main(int argc, char* argv[])
{
   FILE *fStream = fopen(argv[1],"rb");
   if(fStream!=NULL)
    {
       FILE *fStreamOut = fopen(argv[2],"wb");
       if(fStreamOut!=NULL)
        {
           int nHeaderCount = 0;
           _TPacket *myPacket;

           while((myPacket=_makePacket(fStream,100,&nHeaderCount))!=NULL)
            {
               printf("Header\tCount:%d\n",myPacket->Count);
               printf("Len\tCount:%d\n",myPacket->Len);

               if(fwrite(myPacket->Data,myPacket->Len,1,fStreamOut)!=1)
                {
                   printf(" Write I/O error on - \"%s\"\n",argv[2]);
                   free(myPacket->Data);
                   free(myPacket);
                   break;
                }

               free(myPacket->Data);
               free(myPacket);
            };
        }
       else
           printf("Cannot create file - \"%s\"\n",argv[2]);

       fclose(fStreamOut);
    }
   else
       printf("Cannot open file - \"%s\"\n",argv[1]);

   printf("Please, press Enter to exit..");
   getchar();
   fclose(fStream);

   return 0;
}
/*---------------------------------------------------------------------------*/
_TPacket *_makePacket(FILE *fStream,int nSize,int *pnHeaderCount)
{
   /*
    * Store fStream up to nSize bytes from current position and return
    * a _TPacket header.
    *
    * (c) by Directx.
    */
   _TPacket *pPacket = NULL;

   /* Check for invalid stream, if so return pnHeaderCount==-1 and _TPacket NULL */
   if(fStream==NULL || feof(fStream))
    {
       *(int*)pnHeaderCount=-1;
       return  NULL;
    }

   if((pPacket=(_TPacket*)calloc(1,sizeof(_TPacket)))!=NULL)
    {
       memset(pPacket,0,sizeof(_TPacket));
       if((pPacket->Data=(unsigned char*)calloc(1,(nSize+1)*sizeof(unsigned char)))!=NULL)
        {
           int nDataIdx = 0,
               nChar;

           /* Read up to nSize and/or then up to EOF */
           while(nDataIdx++!=nSize)
               if((nChar=fgetc(fStream))!=EOF)
                   pPacket->Data[nDataIdx-1]=nChar;
               else
                   break;

           /* Setup TPacket header details */
           pPacket->Len = nDataIdx-1;
           pPacket->Count = (int)(*(int*)pnHeaderCount)++;
        }
       else
        {
           free(pPacket); pPacket = NULL;
           *(int*)pnHeaderCount=-2;
        }
    }
   else
       *(int*)pnHeaderCount=-3;

   return  pPacket;
}
/*---------------------------------------------------------------------------*/

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Directx και m1cro,χίλια ευχαριστώ για την βοηθεία...Eιναι ότι πρέπει ωστε να αρχίσουμε να το προσεγγίζουμε το πρόβλημα...

 

Και κάτι άλλο που προέκυψε...Προσπαθώ κατα το runtime να αλλάξω το τρέχων μονοπάτι εργασίας.Αυτο προσπαθώ να τοκάνω με την

 

 

chdir(const char * pathname);

 

Ομως ΔΕΝ το αλλάζει το γ@μημ@νο το μονοπάτι.Ακόμα και κυριολεκτική συμβολοσειρά να της διοχετεύσω πάλι το μονοπάτι δεν αλλάζει.Και μέσω

 

και μέσω execvp πήγα να το κάνω αλλα δυστηχώς τίποτα...Βγάζει πάντα Invalid file name...

 

Υπάρχει μήπως καμία ιδέα για το πως θα αλλάξει το current directory;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Η chdir ανήκει στο POSIX, όμως τελικά εδώ όλα εξαρτώνται από τον τρόπο που γίνεται implement εκ της βιβλιοθήκης της.

 

Για παράδειγμα, αν και η chdir δεν μπορεί να αλλάξει την ενεργή μονάδα παρά μόνο τον κατάλογο (που μπορεί να αφορά μια άλλη μονάδα), στον δικό μου compiler αλλάζει και την μονάδα.

 

Ένα απλό παράδειγμα που γυρίζει το ενεργό κατάλογο της διεργασίας στο root της μονάδας C για τα MS-Windows XP, είναι:

 

>
   chdir("c:\\");
   system("dir /p"); /* για να δούμε γρήγορα που είμαστε ... */

 

Από εκεί και πέρα, αν δεν δουλεύει μπορεί να πρέπει να δεις OS specific ρουτίνες.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Mε το chdir λύθηκε ,όλα καλα!!!

 

Εκει που τώρα έχει κολλήσει το πράγμα ειναι στην read...

 

συντάσσω το εξής:

 

sizeOfPacket=read(fp,buf,292);

 

Με τον fp να τον δηλώνω είτε σαν σκέτο int είτε FILE *....

Απο το αρχειο δεν μπορώ να διαβάσω με καμία δύναμη ενω με την scanf ή με την fgets καταφέρνω και τα διαβάζω...

 

Πραγματικά δεν ξέρω τι ειναι και δεν καταφέρνει να τα διαβάσει απο το αρχείο...

 

τον buf το δηλώνω ως εξής:

 

char buf[292];

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Mε το chdir λύθηκε ,όλα καλα!!!

 

Εκει που τώρα έχει κολλήσει το πράγμα ειναι στην read...

 

συντάσσω το εξής:

 

sizeOfPacket=read(fp,buf,292);

 

Με τον fp να τον δηλώνω είτε σαν σκέτο int είτε FILE *....

Απο το αρχειο δεν μπορώ να διαβάσω με καμία δύναμη ενω με την scanf ή με την fgets καταφέρνω και τα διαβάζω...

 

Πραγματικά δεν ξέρω τι ειναι και δεν καταφέρνει να τα διαβάσει απο το αρχείο...

 

τον buf το δηλώνω ως εξής:

 

char buf[292];

FILE *fp;

....

....

....

fread(buf,size*sizeof(char),1,fp);

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Eυχαριστώ βρε παιδια πολύ για την βοήθεια...

 

Μία ακόμη αποριούλα...Πως μπορεί να δω πόσα bytes ακριβώς διάβασε η συνάρτηση ωστε να κατασκευάσω το header του πακέτου;O ασσος που ειναι σαν όρισμα εννοεί οτι όλο αυτο διαβάζεται ενιαιά σαν ένα κομμάτι;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

η απάντηση στον εαυτο μου...

 

#include <stdio.h>

int fread( void *buffer, size_t size, size_t num, FILE *stream );

 

The function fread() reads num number of objects (where each object is size bytes) and places them into the array pointed to by buffer. The data comes from the given input stream. The return value of the function is the number of things read. You can use feof() or ferror() to figure out if an error occurs.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...