C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
И снова работа с файлами, бинарные и текстовые
dayver2009
Отправлено: 18.12.2006, 01:20


Ученик-кочегар

Группа: Участник
Сообщений: 26



Нужно открыть файл (например текстовый .тхт , но не нужно забывать что и все другие файлы то же должны обрабатыватся по етой схеме) и разбить его на блоки по 32 символа
далее берем один блок(например первый) и заносим ASCII двоичный код каждого символа в вектор T[256]

Схема
T[256]={ {0,1,0,0,1,1,1,1},{0,1,1,0,1,0,1,1}, {0,1,1,0,1,1,0,0}, .... ,{0,1,1,0,0,0,1,0}}; (Пример)


T[256]={8 бит 1-го символа,8 бит 2-го символа,8 бит 3-го символа,....,8 бит 32 символа}; (Пояснение структуры)

после математической обработки етого вектора (перемешования) нужно выполнить обратное действие. То биш первые 8 ячеек вектора преобразовать в символ по ASCII коду и записать в другой файл далее вторые 8 ячеек вектора преобразовать в символ по ASCII коду и снова записать в файл и так все 32 символа

Проверять программу я дожен таким образом что если не будет произведено перемешывание ячеек вектора то в второй файл запишется содержымое первого файла без единого отличия
AVC
Отправлено: 18.12.2006, 09:23


Ветеран

Группа: Модератор
Сообщений: 1583



И ??????????

Если есть неясности, то где,
если это предложение работы, то каковы условия оплаты.
dayver2009
Отправлено: 19.12.2006, 18:12


Ученик-кочегар

Группа: Участник
Сообщений: 26



Неясности в том что я не знаю какие функции для етого использовать и как именно что б прога работала по заданым условиям(Именно проблема в работе с файлами(чтение в ячейки вектора, запись в файл) все остальное уже написано и работает)
Grigoriy
Отправлено: 19.12.2006, 18:35


Мастер участка

Группа: Участник
Сообщений: 381



А перемешивание как должно быть ? Самому придумывать как перемешивать ?
dayver2009
Отправлено: 19.12.2006, 18:47


Ученик-кочегар

Группа: Участник
Сообщений: 26



Нет перемешывание идет по заданому алгоритму .Но ето у меня трудностей не вызывает если я имею готовый вектор, а для начала его нужно заполнить из файла что и порождает трудности поскольку я не знаю как ето зделать
AVC
Отправлено: 19.12.2006, 19:06


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (dayver2009 @ 19.12.2006, 17:12)
проблема в работе с файлами

Мне, как старому сишнику, как-то ближе функции fopen, fread. Но можно работать и через потоки и функциями форматированного ввода-вывода.
Все зависит от того как конкретно у вас записана информация в файле.
Если это "например текстовый .тхт " то это одно, а если двоичный — другое.
Doga
Отправлено: 19.12.2006, 20:04


Мастер участка

Группа: Участник
Сообщений: 575



Вот код, который заполняет Ваш вектор T[256] 32мя символами из буфера char *FileBuffer , в который предварительно было загружено содержимое файла.

CODE

         int ArrayPosition = 0;
         
         for (int k = 0; k < 32; k++)
         {
           for (int i = 0; i < 8; i++)
           {
             T[ArrayPosition] = (FileBuffer[k]>>i)&1;
             ArrayPosition++;
           }
         }


В каждом наборе из 8ми элементов массива младший бит идет первым, а старший — последним.
dayver2009
Отправлено: 19.12.2006, 21:29


Ученик-кочегар

Группа: Участник
Сообщений: 26



QUOTE (Doga @ 19.12.2006, 20:04)
Вот код, который заполняет Ваш вектор T[256] 32мя символами из буфера char *FileBuffer , в который предварительно было загружено содержимое файла.
...

Получается в буфер char *FileBuffer нужно загрузить уже не данные(символы) из файла, а уже их ASCII двоичный код(32 групы, в каждой групе содержытся 8 разрядное число в двоичной системе счисления которое соответствует по ASCII таблице символу из файла)

Если так то перед решением задачи конвертирования данных файла в ASCII код(которую я попытаюсь сам решыть поскольку есть наработки) нужно решыть следующую проблему (Которую я сам не смогу одолеть — в чем и прошу Вас помочь)которая заключается в том что анализируемый файл должен быть любого типа , как "например текстовый .тхт " так и двоичный (Ето вот то что уточняет AVC).

QUOTE (AVC @ 19.12.2006, 19:06)
...  
Все зависит от того как конкретно у вас записана информация в файле.
Если это "например текстовый .тхт " то это одно, а если двоичный — другое.
Doga
Отправлено: 20.12.2006, 18:18


Мастер участка

Группа: Участник
Сообщений: 575



Вообще то, разница между "текстовыми" и "двоичными" файлами чисто условная. Там байты и здесь тоже байты. Только для текстовых фалов все содержащиеся в файле байты имеют символьный вид, а для двоичных — не все. Ни кто не запрещает Вам работать с текстовым файлом как с двоичным. Да и в буфер типа char * можно загрузить любое содержимое. smile.gif

Если Ваши двоичные файлы — это всего лишь результат смешивания, то разницы между TXT и BIN в этом случае нет никакой. wink.gif

Другое дело — какой-либо особенный формат двоичного файла. Но тут уж Вам решать самому.
AVC
Отправлено: 20.12.2006, 19:00


Ветеран

Группа: Модератор
Сообщений: 1583



Под текстовыми я подразумеваю те файлы в которых данные хранятся во внешнем представлении а под двоичными — те, в котороых данные хранятся во внутреннем предсавлении.

Для того, что бы зачитывать файл любого типа (сиречь формата) можно поставить простой селектор (if) и выполнять загрузку той функцией, которая правильно читает данный формат.
dayver2009
Отправлено: 20.12.2006, 21:32


Ученик-кочегар

Группа: Участник
Сообщений: 26



Ну скорее всего подойдет внутренее представление (то биш двоичные файлы), ну а для текстового поставим иф.

А что такое — сиречь? и как указать в (if) формат файла(то что идет в его имени после точки)?
тоесть нужно написать

if("Что здесь нужно написать"==txt){.... ;}
else {....;}

И вот подходим к основному — какие функции использовать для тхт а какие для двоичных?И как это зделать?
AVC
Отправлено: 21.12.2006, 11:04


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

и как указать в (if) формат файла(то что идет в его имени после точки)?

В имени после точки идет расширение имени (тип) а формат это то как данные хранятся внутри файла. Как его указывать об этом надо договориться с поставщиком файлов. Например некая "магическая" последовательность в имени или прямо внутри файла. Я предпочитаю второй вариант.
Т.е. сначала узнаете формат хранения данный а потом вызываете соответствующую функцию.

QUOTE

какие функции использовать для тхт а какие для двоичных

Это не основное. Можно использовать одни и те же. Основное это то, что код всегда работает с внутренним представлением к которому и нужно привести прочитанную информацию.

Приведу пример:
Допустим у меня в файле хранятся координаты левого верхнего угла и размер прямоугольника — 4 целых числа во внешнем представлении через запятую. Для использования их, например, в качестве координат окна я могу воспользоваться подобным кодом:
CODE

/*
содержимое файла qwe.b
100, 200, 300, 400
*/

int x0, y0, xl, yl;
x0 = y0 = xl = yl = 0;
FILE *fp = fopen((ExtractFilePath(Application->ExeName)+"qwe.b").c_str(), "r");
if (!fp) return;
fscanf(fp, "%d, %d, %d, %d", &x0, &y0, &xl, &yl);
fclose(fp);

или таким
CODE

x0 = y0 = xl = yl = 0;
char c;
ifstream cinp((ExtractFilePath(Application->ExeName)+"qwe.b").c_str());
cinp >> x0 >> c >> y0 >> c >> xl >> c >> yl;
cinp.close();


QUOTE

Ну скорее всего подойдет внутренее представление (то биш двоичные файлы)

Повторюсь — мало знать что это "внутренее представление" надо знать (договориться с поставщиком) что, как и в каком порядке храниться в файле.
dayver2009
Отправлено: 22.12.2006, 00:26


Ученик-кочегар

Группа: Участник
Сообщений: 26



Для ясности поясню суть программы которую я пишу (с Вашей помощью):
Прога предназначена для студентов изучающих криптографию.Прога будет шыфровать файлы по приметивному алгоритму — "круговой сдвиг".
Принцып действия таков — как я уже говорил считывается из файла (любой файл текстовый, видео,звуковой и вообще любой любой) 32 байта (символа, включая непечатаемые и NULL — если ето текстовый файл) потом каждый байт(символ) превращается в последовательность из восьми 0 и 1 по коду ASCII для етого символа(байта) (например если мы считываем символ "F" — тогда мы превращаем его в цыфру 70 в двоичном коде а именно "01000110" а если мы считываем NULL символ то у нас будет цыфра "00000000") Вот как раз ети 0 и 1 мы и записываем в вектор Т[256] (256 — число ячеек вектора /8 — разрядов кода ASCII = 32 — байта содержымого файла) — первый блок обрабатываемый за один проход цыкла шыфрования.

Далее происходит шыфрование (перемешывание, здвиг , или что то еще) — содержымое ячеек вектора Т меняет свое положение.

Потом "сохраняем" результат шыфрования в другой файл — из вектора Т по очереди извлекаем по 8 ячеек и превращаем ету последовательность в символ(байт) и записываем етот символ(байт) в файл.

Вот вся работа программы.

Исходя из задачи — непредставляется возможности "договорится с поставщиком"

Возвращаясь к приведенному примеру файла "qwe.b" в котором записаны последовательно такие символы :
"1" , "0" , "0" , "," , "символ пробела" , "2" , "0" , "0" ну и так далее всего 18 символов + еще по идее 1 символ конца файла который мы не считываем из исходного файла. Ети 18 символов превратятся в 144 нулей и одиниц записаних в вектор Т[256] (все остальные ячейки заполняются 0)

ВНИМАНИЕ! а теперь вопрос :Есть ли функция (и как ею пользоватся) которая запишет в поток (к примеру char *FileBuffer) последовательность 0 и 1 которая соответствует 18 символам(байтам) файла "qwe.b" Для того что б потом заполнить вектор Т по коду который предложыл Doga .
Как я понял коды написаные AVC етого не делают.Они возвращают переменным int x0, y0, xl, yl значения записаные в файле.
AVC
Отправлено: 22.12.2006, 09:40


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

Как я понял коды написаные AVC етого не делают

Естественно. Они приведены в качестве примера для иллюстрации чтения числовых данных из внешнего представления.
А пример понадобился из-за нечетко поставленной проблеммы.

QUOTE

Принцып действия таков — как я уже говорил считывается из файла 32 байта

Ну теперь понятно. У вас на входе просто поток байтов.
CODE

char buf[32];
FILE *fi = fopen((ExtractFilePath(Application->ExeName)+"qwe.b").c_str(), "rb");
FILE *fo = fopen((ExtractFilePath(Application->ExeName)+"qwe.bb").c_str(), "wb");
if (!fi || !fo) return;

for (int cou = fread(buf, 1, sizeof(buf), fi); cou > 0; cou = fread(buf, 1, sizeof(buf), fi))
{  while (cou < sizeof(buf)) buf[cou++] = 0x00;
   // тут преобразуем в вектор и перемешиваем

// и что то надо делать с хвостом для выполнения условия
// если не будет произведено перемешывание ячеек вектора
// то в второй файл запишется содержымое первого файла
// без единого отличия
// например сохранить и писать оригинальный cou байт

   fwrite(buf, 1, sizeof(buf), fo);
}

fclose(fi);
fclose(fo);

dayver2009
Отправлено: 23.12.2006, 19:53


Ученик-кочегар

Группа: Участник
Сообщений: 26



Спасибо!

Думаю разберусь.

Но если подскажете как вложыть етот код (считывания 32 байтов) в цыкл счытывания всего файла (шаг цыкла — считываение 32 байт. И кстати проблема "хвоста" для выполнения условия ... не будет проблемой если етот хвост будет только в последнем шаге цыкла счытывания 32 байт файла — а по идее оно именно так и должно быть) я буду беспредельно благодарен за еще раз оказаную помощь.

Как я понимаю при переходе на следующий шаг цыкла счытывания 32 байт нужно перемещать указатель счытывания и записи?
AVC
Отправлено: 25.12.2006, 09:54


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (dayver2009 @ 23.12.2006, 18:53)

...Но если подскажете как вложыть етот код  (считывания 32 байтов) в цыкл счытывания всего файла (шаг цыкла — считываение 32 байт)...

ohmy.gif ohmy.gif ohmy.gif
Присмотритесь, ведь пример так и считывает входной поток блоками по sizeof(buf) байт от позиции перед входом в цикл до конца файла.
CODE

for (int cou = fread(buf, 1, sizeof(buf), fi); cou > 0; cou = fread(buf, 1, sizeof(buf), fi))
{  while (cou < sizeof(buf)) buf[cou++] = 0x00;
  // тут преобразуем в вектор и перемешиваем результат в buf
  fwrite(buf, 1, sizeof(buf), fo);
}


QUOTE

И кстати проблема "хвоста" для выполнения условия ... не будет проблемой если етот хвост будет только в последнем шаге цыкла счытывания

Да, она возникнет только в последнем шаге, но на самом деле это не важно, так как она обязана решаться уровнем выше. Шифрование не нужно — запускаем простое копирование входного файла в выходной, и тут нужно воспользоваться функциями ос, как более эфективными.

dayver2009
Отправлено: 25.12.2006, 18:57


Ученик-кочегар

Группа: Участник
Сообщений: 26



Извеняюсь(Виноват — не внимательно читал код примера), действительно пример реализует цыкл считывания 32 байт.

Еще раз огромное СПАСИБО!



Кстати всех с наступающим Новым годом и Рождеством.

Вернуться в Вопросы программирования в C++Builder