Нужна помощь в переносе этого кода C на C # - PullRequest
1 голос
/ 17 июля 2010

Я не очень хорош в c на всех.Я попытался раскрыть суть того, что код C делает в C #, используя эту статью wikipedia .Однако моя версия полностью отличается и не обеспечивает такое же сжатие, как код C.Поэтому я хотел бы перенести следующий код с C на C #.Тем не менее, мне не нужно для чтения / записи в файлы.

Я не знаком с тем, как чтение и запись файлов работает в Си. Поэтому весь пух, связанный с файлами, смущает меня.Также эти строки немного сбивают с толку: token = i - 1 | 0x80; и 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;
}

Любая помощь очень ценится.

Ответы [ 3 ]

3 голосов
/ 17 июля 2010

По вашему вопросу файла я настоятельно рекомендую обратиться к документации по стандартной библиотеке C.

fread fwrite

token = i - 1 | 0x80; 

i минус 1, |выполняет побитовую операцию ИЛИ, в этом случае устанавливает 8-й бит в токене.

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

token & ~0x80 принимает НЕ 0x80 (все биты, кроме старшего бита) и выполняет побитовое И (бит установленкогда оба бита установлены).В этом случае он возвращает все, кроме 8-го бита.

Что касается того, что это означает в вашем случае, посмотрите несколько статей о RLE.

1 голос
/ 17 июля 2010
/* 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 голос
/ 17 июля 2010
token = i - 1 | 0x80;

Символ | является побитовым ИЛИ, поэтому он объединяет i - 1 с 0x80 (шестнадцатеричное для 128).Я оставлю вам исследование побитовых операций.

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

& - это побитовое И, в то время как ~ отрицает следующее значение (переключает 1 и 0)Так что:

~1111000 = 00001111

Кстати, все эти операторы находятся в C # и работают более или менее одинаково.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...