2010-07-17 5 views
1

Je ne suis pas très bon en c du tout. J'ai essayé de capturer l'essence de ce que le code C fait en C# en utilisant cet article wikipedia. Cependant, ma version est totalement différente et n'obtient pas la même compression que le code C. Par conséquent, je voudrais porter le code suivant de C à C#. Cependant, je n'en ai pas besoin pour lire/écrire dans des fichiers.Besoin d'aide pour porter ce code C à C#

Je ne suis pas familier avec la façon dont la lecture et l'écriture de fichiers fonctionne en C. Par conséquent, tout le fluff lié au fichier me confond. Aussi ces lignes sont un peu confus: token = i - 1 | 0x80; et length = (token & ~0x80) + 1;

/****************************************************************************** 
* LoadRLE/SaveRLE - Load and save binary data using RLE compression. 
* Run-length tokens have a set MSB, while data tokens have a cleared 
* MSB. The value of the token's remaining bits plus one indicates the 
* length of the block. The minimum run length is three bytes, while 
* the maximum is 128. 
* 
* data - Array holding data to load or save. 
* size - Size of the data array. 
* file - The file pointer to use. 
* return - Total number of bytes read from or written to data[]. 
*/ 
size_t SaveRLE (unsigned char data[], size_t size, FILE *file) 
{ 
    unsigned char token; 
    unsigned int i; 
    size_t total = 0; 

    while(size) 
    { 
     /*This loop identifies blocks of repeating data:*/ 
     i = 2; 
     while(i < size && i < 128 && 
      data[i] == data[i - 1] && data[i - 1] == data[i - 2]) 
      i++; 
     /*If repeating data was found, save it:*/ 
     if(i > 2){ 
      token = i - 1 | 0x80; 
      if(!fwrite(&token, 1, 1, file)) 
       return total; 
      if(!fwrite(data, 1, 1, file)) 
       return total; 
      data += i, size -= i, total += i; 
     } 

     /*This loop identifies blocks of non-repeating data:*/ 
     i = 0; 
     while(i < size && i < 128 && (i + 2 > size ? 1 : 
      data[i] != data[i + 1] || data[i + 1] != data[i + 2])) 
      i++; 
     /*If non-repeating data was found, save it:*/ 
     if(i){ 
      token = i - 1; 
      if(!fwrite(&token, 1, 1, file)) 
       return total; 
      if(fwrite(data, 1, i, file) != i) 
       return total; 
      data += i, size -= i, total += i; 
     } 
    } 

    return total; 
} 

size_t LoadRLE (unsigned char data[], size_t size, FILE *file) 
{ 
    unsigned char token; 
    unsigned int length; 
    size_t total = 0; 

    while(size && fread(&token, 1, 1, file)){ 
     length = (token & ~0x80) + 1; 
     if (length > size) 
      return total; 
     if(token & 0x80){ 
      if(!fread(&token, 1, 1, file)) 
       return total; 
      memset(data, token, length); 
     }else{ 
      if(fread(data, 1, length, file) != length) 
       return total; 
     } 
     data += length, size -= length, total += length; 
    } 
    return total; 
} 

Toute aide est grandement appréciée.

+4

Mike, vous devrez faire un plus grand effort. SO ne va pas écrire des morceaux de code pour vous. Apprenez C, apprenez C# puis * faites-le *. –

+5

Veuillez lire à nouveau mon message. Je demande simplement de l'aide pour des parties spécifiques. Si vous n'avez pas le temps de lire le message, veuillez ne pas laisser de commentaire disant apprendre le C et le C#. Ce n'est pas très utile du tout. – Mike

+3

Pourquoi les gens reviennent-ils sur le commentaire d'Eli? Il n'a clairement pas lu le titre de la question. –

Répondre

1
/* 0 */ 
unsigned char token; 
unsigned char data[]; 
FILE *file; 

/* 1 */ 
if(!fwrite(&token, 1, 1, file)) 
    return total; 

/* 2 */ 
if(!fwrite(data, 1, 1, file)) 
    return total; 

/* 3 */ 
if(fwrite(data, 1, i, file) != i) 
    return total; 

/* 4 */ 
if(!fread(&token, 1, 1, file)) 
    return total; 

/* 5 */ 
if(fread(data, 1, length, file) != length) 
    return total; 

/* 6 */ 
while(size && fread(&token, 1, 1, file)) 

/* 7 */ 
data += i; 
data[i];

/* 0 */ 
int token; // I'm using 'int' here to easier read single byte from Stream object, in your C code 'token' variable does not overflow so there will be no problem with that is has other type then 'byte' 
byte[] data; 
int data_pos = 0; // instead of moving 'data' pointer use additional index variable 
Stream file; // some stream to read/write bytes 

try { 
    /* 1 */ 
    file.WriteByte((byte)token); 

    /* 2 */ 
    file.Write(data, data_pos, 1); 

    /* 3 */ 
    file.Write(data, data_pos, i); 

    /* 4 */ 
    if ((token = file.ReadByte()) < 0) 
     return total; 

    /* 5 */ 
    if (file.Read(data, data_pos, length) < length) 
     return total; 

    /* 6 */ 
    while((size != 0) && ((token = file.ReadByte()) >= 0)) 

    /* 7 */ 
    data_pos += i; 
    data[data_pos + i]; 

} catch (IOException e) { 
    return total; 
}
1
token = i - 1 | 0x80; 

Le symbole | est un OU binaire, il est donc la combinaison i - 1 avec 0x80 (hex pour 128). Je vais laisser la recherche dans les opérations au niveau du bit à vous.

length = (token & ~0x80) + 1; 

Le & est Bitwise ET, alors que la valeur ~ nie suivante (flips les 1 et 0). Alors que:

~1111000 = 00001111 

Soit dit en passant, tous ces opérateurs sont en C# et travaillent dans plus ou moins de la même façon.

3

Pour votre question de fichier, je suggère fortement de consulter la documentation de la bibliothèque standard C.

freadfwrite

token = i - 1 | 0x80; 

i moins 1, | effectue une opération OU au niveau du bit, en définissant dans ce cas le huitième bit du jeton.

length = (token & ~0x80) + 1; 

token & ~0x80 prend le pas de 0x80 (tous les bits, mais le bit) et fait une opération de bits AND (bit est défini lorsque les deux bits sont). Dans ce cas, il renvoie tous sauf le huitième bit.

En ce qui concerne ce que cela signifie dans votre cas, regardez quelques articles sur RLE.

+0

Merci d'avoir clarifié certaines choses pour moi. Ces liens ont aidé. Cependant, j'aurais dû m'expliquer un peu plus. Je ne suis pas confus avec les opérations au niveau du bit. Je suis confus au sujet du choix de 128 ou 0x80 et pourquoi il est or'd avec i-1. – Mike

+1

Cela est spécifique à leur implémentation de RLE: http://en.wikipedia.org/wiki/Run-length_encoding. Il semble que le bit haut est utilisé pour signaler un jeton de répétition dans cette version. –

+0

Petite note: le commentaire inclus avec le code dans la question explique _exactement_ comment fonctionne cette implémentation RLE. Tout ce que vous devez savoir, c'est que MSB = bit le plus significatif = bit le plus élevé = 0x80 – Nyerguds

Questions connexes