2015-07-23 3 views
-1

Во-первых, я работаю с большим двоичным файлом (2-4 ГБ) на Linux 64bit, и этот файл также сопоставляется с другим процессом. Таким образом, содержимое в файле постоянно меняется. Я хотел бы изменить бит в конкретном бите/местоположении, но не должен его читать.Изменение конкретного бита в большом двоичном файле

Простое изменение бита по конкретному адресу и не заботятся о его содержимом. дополнительное редактирование: или установить бит, который будет зависеть все время. (этот бит не может быть изменен)

, когда я использую hexdump для его чтения, похоже на это.

3ffbd280 00 00 78 32 fb 44 22 cc 44 11 22 aa b2 33 b2 c3 

Любые мысли или идеи очень приветствуются.

+0

I пока еще не совсем уверен и все еще нахожу метод. –

+1

Посмотрите 'fseek'. –

+1

Вам нужно установить бит, сбросить бит или переключить бит? Будет сложно, если не невозможно, настроить один бит, не читая, по крайней мере, байт, содержащий этот бит заранее. Как определяется бит? У вас есть бит во всем файле или номер байта и номер бита в байте? Вы на 32-битной или 64-битной машине? –

ответ

1

С 64-разрядной версией Linux подпись fseek() не вызывает проблем; параметр offset - это long, что означает, что он будет 64-битным количеством и может легко обрабатывать файл размером 2-4 гигабайта. Если бы вопрос касался 32-разрядного Linux или для 64-битной Windows, история была бы иной. У вас возникнут проблемы с смещениями между 2 GiB и 4 GiB.

Предположим, что поток файлов открыт для чтения и записи. Предположим, что позиция бита задается через абсолютное смещение байта в файле плюс число бит (0 ... 7). Предположим, что бит должен измениться, поэтому операция переключает бит от 1 до 0 или от 0 до 1. Предположим, что нет необходимости хранить запись текущей позиции в файле, чтобы ее можно было восстановить после переброса бит. Затем последовательность операций может быть:

void flip_bit(FILE *fp, long offset, int bitno) 
{ 
    int c; 
    assert(fp != 0); 
    assert(offset >= 0); 
    assert(bitno >= 0 && bitno < 8); 

    fseek(fp, offset, SEEK_SET); 
    if ((c = getc(fp)) != EOF) 
    { 
     c ^= 1 << bitno; 
     fseek(fp, -1L, SEEK_CUR); // Step backwards 1 byte 
     putc(c, fp); 
     fflush(fp); 
    } 
} 

Каждое допущение, которое вы изменяете, вызывает соответствующие изменения кода. Нужно fflush(fp);, чтобы максимизировать вероятность внесения изменений на диск, чтобы другой процесс его видел. Кроме того, fflush(fp) означает, что это безопасно использовать поток для входа (или выхода) даже без вмешательства искать (ISO/IEC 9899: 2011 §7.21.5.3 The fopen функции, ¶7):

Когда файл открывается с режимом обновления ('+' в качестве второго или третьего символа в выше списка значений аргумента режима), как вход и выход могут выполняться в связанном потоке .Однако выход не должен быть непосредственно с последующим входом без промежуточного вызова функции fflush или к функции позиционирования файла (fseek, fsetpos или rewind), и ввод не должен непосредственно следовать за выходом без промежуточного вызова функция позиционирования файла, если только операция ввода не завершает работу с файлом.

Если вы хотите, чтобы гарантировать, что бит установлен, то замените назначение:

 c |= 1 << bitno; 

Если вы хотите, чтобы обеспечить бит сбрасывается, замените назначение:

 c &= ~(1 << bitno); 
+0

Соответствует ли смещение «бит/байтовый адрес в целом файле»? –

+0

Да. Смещение - это позиция байта в файле, начиная со смещения нуля для первого байта и т. Д. Номер бит в байте является отдельным. При желании вы можете кодировать вещи по-разному. Но вопрос не был ясен о том, как бит перевернуться, и я выбрал самое простое решение. Есть много вариантов, которые вы могли бы использовать. Если файл переводится в память в процессе перевертывания бит, тогда требуется целое альтернативное решение. –

+0

Это было успешно, спасибо вам большое за помощь –

1
FILE* fp = fopen("bigfile.abc", "rb+") 
//rb+ is important! see here: the wrong mode may clear/delete the file. 
//http://www.cplusplus.com/reference/cstdio/fopen/?kw=fopen 

if(fp) 
{ 
    unsigned char b = 0; 
    fseek(fp, #_of_bytes_from_origin, SEEK_SET) 
    fread(&b, 1, 1, fp);  //read 1 unit of 1 byte into 'b' 

    b ^= (1<<bit_index);  //toggle the bit, as Jonathan said 

    fseek(fp, -1, SEEK_CUR); //go one byte backwards (you went forwards when reading) 
    fwrite(&b, 1, 1, fp);  //write 1 unit of 1 byte back into the file 
    fclose(fp);     //close the file when done 
} 

Это только мой опыт с C на 32-разрядных машинах на протяжении многих лет, но я не думаю, что из вышеперечисленного изменится на 64-битной архитектуре, так как вы будучи явно около одного байт.

См: http://www.cplusplus.com/reference/cstdio/ и основные файловые функции: FOPEN(), fclose(), FSEEK(), ftell(), Fread(), FWRITE()

Изменение конкретного бита:

byte_to_change &= ~(1<<bit_index) 

где bit_index 0 до 7. Это установит бит в 0.

byte_to_change |= (1<<bit_index) 

установит его в 1.

+3

Я бы предположил, что термины должны быть «сбросить бит в 0» и «установить бит в 1». Вы можете добавить 'byte_to_change^= (1 << бит_индекс);' to 'переключить бит', то есть перевернуть его на 0, если оно равно 1, и перевернуть его на 1, если оно равно 0. –

+0

Я пытаюсь это сделать. –

+0

И вход, и, что более важно, * выход * указанной операции отсутствует. Изменение байта в памяти сделает OP мало пользы, пока байт не будет записан обратно в сопоставленный файл, чтобы другой процесс мог его увидеть. – WhozCraig

Смежные вопросы