1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//Произвольное позиционирование в файле Visual Studio 17 Листинг #1 #include <iostream> #include <fstream> using namespace std; int main() { const char* PATH = "C:\\MyFiles\\4.txt"; /*ЗАПИСЬ В ФАЙЛ ЛВСЕХ СИМВОЛОВ АТИНСКОГО АЛФАВИТА*/ ofstream f1(PATH); for (char i = 'A'; i < 'Z'; i++) { f1 << i; }; f1.close(); char value = 0; /*ЧТЕНИЕ ИЗ ФАЙЛА ПРОИЗВОЛЬНОГО СИМВОЛА*/ ifstream f2(PATH); f2.seekg(5 * sizeof(char), ios::beg); //<--- устанавливаем курсор чтения на (пятый + 1) символ f2 >> value; //считываем символ, курсор смещается на одну позицию вперёд cout << value; //узнаём считанное значение, это символ F f2.close(); cin.get(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//Произвольное позиционирование в файле Visual Studio 17 Листинг #2 #include <iostream> #include <fstream> using namespace std; int main() { const char* PATH = "C:\\MyFiles\\4.txt"; /*ЗАПИСЬ В ФАЙЛ ЧИСЕЛ 5...14*/ ofstream f1(PATH); for (int i = 5; i < 15; i++) { f1.write((char*)&i, sizeof(int)); }; f1.close(); int value = 0; //Обратите внимание, что тип для сохранения //считваемого значения был изменён относительно листинга #1 /*ЧИТАЕМ ПРОИЗВОЛЬНОЕ ЗНАЧЕНИЕ ИЗ ФАЙЛА В ПЕРЕМЕННУЮ value*/ ifstream f2(PATH); f2.seekg(5 * sizeof(int), ios::beg); //смещаем курсор на 5 позиций от начала файла f2.read((char*)&value, sizeof(int)); cout << value << '\n'; //на выводе получаем 10 f2.close(); cin.get(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
//Произвольное позиционирование в файле, изменение хранимых данных Visual Studio 2017 Листинг #3.1 #include <iostream> #include <fstream> using namespace std; /*ФУНКЦИЯ СОЗДАНИЯ НОВОГО ФАЙЛА*/ void file_create(const char* PATH) { ofstream f1(PATH, ios::binary); for (int i = 5; i < 15; i++) { f1.write((char*)&i, sizeof(int)); } f1.close(); } /*ФУНКЦИЯ ОБХОДА ФАЙЛА*/ void file_read(const char* PATH) { ifstream f1(PATH, ios::binary); int value = 0; while (!f1.eof()) { f1.read((char*)&value, sizeof(int)); if (!f1) break; cout << value << '\n'; } f1.close(); } /*ФУНКЦИЯ ПЕРЕЗАПИСИ ЗНАЧЕНИЙ В ФАЙЛЕ*/ void file_change(const char* PATH) { ofstream f1(PATH, ios::in | ios::binary | ios::ate); int cursor = 1 * sizeof(int); //Начальная позиция курсора будет смещена на 1 int int value = 0; //записываемое в файл значение int final_position = f1.tellp(); //запоминаем позицию курсора (сейчас он мигает в конце файла, файл открыт для дозаписи в конец) while (cursor < final_position && f1.seekp(cursor, ios::beg)) { //пока курсор не вылез за конец файла и смещение курсора даёт положительный ответ, выполняем запись в файл значений f1.write((char*)&value, sizeof(int)); //Записываем значение value в файл cursor += (2 * sizeof(int)); //Смещаем курсор на 2 int } f1.close(); } int main() { const char* PATH = "C:\\MyFiles\\4.txt"; int X = 0; cout << "OUR CASE: \n"; cout << "1. create new file. \n"; cout << "2. read file. \n"; cout << "3. rechange file. \n"; cin >> X; cout << "\n===========\n"; switch (X) { case 1: file_create(PATH); break; case 2: file_read(PATH); break; case 3: file_change(PATH); break; default: break; } cin.get(); cin.get(); } |
Это обусловлено тем, что для разных типов разный шаг смещения. Чем шире тип — тем шире шаг.
1 |
int final_position = f1.tellp(); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
//Произвольное позиционирование в файле Visual Studio 17 Листинг #3.2 #include <iostream> #include <fstream> #include <cstdint> using namespace std; /*ФУНКЦИЯ СОЗДАНИЯ НОВОГО ФАЙЛА*/ void file_create(const char* PATH) { ofstream f1(PATH, ios::binary); for (uint8_t i = 5; i < 15; i++) { f1.write((char*)&i, sizeof(uint8_t)); } f1.close(); } /*ФУНКЦИЯ ОБХОДА ФАЙЛА*/ void file_read(const char* PATH) { ifstream f1(PATH, ios::binary); uint8_t value = 0; while (!f1.eof()) { f1.read((char*)&value, sizeof(uint8_t)); if (!f1) break; cout << static_cast<int>(value) << '\n'; //После кода пояснение нужности приведения типа } f1.close(); } /*ФУНКЦИЯ ПЕРЕЗАПИСИ ЗНАЧЕНИЙ В ФАЙЛЕ*/ void file_change(const char* PATH) { ofstream f1(PATH, ios::in | ios::binary | ios::ate); uint8_t cursor = 1 * sizeof(uint8_t); //Начальная позиция курсора будет смещена на 1 uint8_t uint8_t value = 0; //записываемое в файл значение uint8_t final_position = f1.tellp(); //запоминаем позицию курсора (сейчас он мигает в конце файла, файл открыт для дозаписи в конец) while (cursor < final_position && f1.seekp(cursor, ios::beg)) { //пока курсор не вылез за конец файла и смещение курсора даёт положительный ответ, выполняем запись в файл значений f1.write((char*)&value, sizeof(uint8_t)); //Записываем значение value в файл cursor += (2 * sizeof(uint8_t)); //Смещаем курсор на 2 uint8_t } f1.close(); } int main() { const char* PATH = "C:\\MyFiles\\4.txt"; int X = 0; cout << "OUR CASE: \n"; cout << "1. create new file. \n"; cout << "2. read file. \n"; cout << "3. rechange file. \n"; cin >> X; cout << "\n===========\n"; switch (X) { case 1: file_create(PATH); break; case 2: file_read(PATH); break; case 3: file_change(PATH); break; default: break; } cin.get(); cin.get(); cout << sizeof(uint8_t) << '\n';; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
//Произвольное позиционирование в файле Visual Studio 17 Листинг #4.1 #include <iostream> #include <fstream> #include <cstdint> using namespace std; /*ФУНКЦИЯ СОЗДАНИЯ НОВОГО ФАЙЛА*/ void file_create(const char* PATH) { ofstream f1(PATH, ios::binary); for (uint8_t i = 5; i < 15; i++) { f1.write((char*)&i, sizeof(uint8_t)); } f1.close(); } /*ФУНКЦИЯ ОБХОДА ФАЙЛА*/ void file_read(const char* PATH) { ifstream f1(PATH, ios::binary); uint8_t value = 0; while (!f1.eof()) { f1.read((char*)&value, sizeof(uint8_t)); if (!f1) break; cout << static_cast<int>(value) << '\n'; //После кода пояснение нужности приведения типа } f1.close(); } /*ФУНКЦИЯ ПЕРЕЗАПИСИ ЗНАЧЕНИЙ В ФАЙЛЕ*/ void file_change(const char* PATH) { ofstream f1(PATH, ios::in | ios::binary | ios::ate); uint8_t cursor = 1 * sizeof(uint8_t); //Начальная позиция курсора будет смещена на 1 uint8_t uint8_t value = 0; //записываемое в файл значение streampos final_position = f1.tellp(); //запоминаем позицию курсора (сейчас он мигает в конце файла, файл открыт для дозаписи в конец) while (cursor < final_position && f1.seekp(cursor, ios::beg)) { //пока курсор не вылез за конец файла и смещение курсора даёт положительный ответ, выполняем запись в файл значений f1.write((char*)&value, sizeof(uint8_t)); //Записываем значение value в файл cursor += (2 * sizeof(uint8_t)); //Смещаем курсор на 2 uint8_t } f1.close(); } void file_update(const char* PATH) { uint8_t value; //считываемое из файла значение fstream f1(PATH, ios::in | ios::out | ios::ate); //поток открыт одновременно и для записи и для чтения int cursor = 1 * sizeof(int8_t); //начальная позиция курсора смещена на одно значение, на int8_t байтов while (f1.seekg(cursor, ios::beg)) { //двигаем курсор, пока двигается if (!f1.read((char*)&value, sizeof(value))) { //читаем значение из файла и запоминаем его в value break; //если попытка очередного чтения выключила флаг f1.good(), выходим из while } if (f1.seekp(cursor, ios::beg)) { //устанавливаем курсор для записи на позицию value += 10; //если всё хорошо, то изменяем прочитанное число f1.write((char*)&value, sizeof(value)); //и записываем это число поверх прочтённого } cursor += 2 * sizeof(uint8_t); //обязательно двигаем курсор на новое число } } int main() { const char* PATH = "C:\\MyFiles\\4.txt"; int X = 0; cout << "OUR CASE: \n"; cout << "1. create new file. \n"; cout << "2. read file. \n"; cout << "3. rechange file. \n"; cout << "4. update file. \n"; cin >> X; cout << "\n===========\n"; switch (X) { case 1: file_create(PATH); break; case 2: file_read(PATH); break; case 3: file_change(PATH); break; case 4: file_update(PATH); break; default: break; } cin.get(); cin.get(); cout << sizeof(uint8_t) << '\n';; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
//Произвольное позиционирование в файле Visual Studio 17 Листинг #4.2 #include <iostream> #include <fstream> #include <cstdint> using namespace std; /*ФУНКЦИЯ СОЗДАНИЯ НОВОГО ФАЙЛА*/ void file_create(const char* PATH) { ofstream f1(PATH, ios::binary); for (uint8_t i = 5; i < 15; i++) { f1.write((char*)&i, sizeof(uint8_t)); } f1.close(); } /*ФУНКЦИЯ ОБХОДА ФАЙЛА*/ void file_read(const char* PATH) { ifstream f1(PATH, ios::binary); uint8_t value = 0; while (!f1.eof()) { f1.read((char*)&value, sizeof(uint8_t)); if (!f1) break; cout << static_cast<int>(value) << '\n'; //После кода пояснение нужности приведения типа } f1.close(); } /*ФУНКЦИЯ ПЕРЕЗАПИСИ ЗНАЧЕНИЙ В ФАЙЛЕ*/ void file_change(const char* PATH) { ofstream f1(PATH, ios::in | ios::binary | ios::ate); uint8_t cursor = 1 * sizeof(uint8_t); //Начальная позиция курсора будет смещена на 1 uint8_t uint8_t value = 0; //записываемое в файл значение streampos final_position = f1.tellp(); //запоминаем позицию курсора (сейчас он мигает в конце файла, файл открыт для дозаписи в конец) while (cursor < final_position && f1.seekp(cursor, ios::beg)) { //пока курсор не вылез за конец файла и смещение курсора даёт положительный ответ, выполняем запись в файл значений f1.write((char*)&value, sizeof(uint8_t)); //Записываем значение value в файл cursor += (2 * sizeof(uint8_t)); //Смещаем курсор на 2 uint8_t } f1.close(); } void file_update(const char* PATH) { uint8_t value; //считываемое из файла значение fstream f1(PATH, ios::in | ios::out | ios::ate); //поток открыт одновременно и для записи и для чтения int cursor = 1 * sizeof(int8_t); //начальная позиция курсора смещена на одно значение, на int8_t байтов while (f1.seekg(cursor, ios::beg)) { //двигаем курсор, пока двигается if (!f1.read((char*)&value, sizeof(value))) { //читаем значение из файла и запоминаем его в value break; //если попытка очередного чтения выключила флаг f1.good(), выходим из while } if (f1.seekp(cursor, ios::beg)) { //устанавливаем курсор для записи на позицию value += 10; //если всё хорошо, то изменяем прочитанное число f1.write((char*)&value, sizeof(value)); //и записываем это число поверх прочтённого } cursor += 2 * sizeof(uint8_t); //обязательно двигаем курсор на новое число } } bool menu(const char* PATH) { int X = 0; cout << "OUR CASE: \n"; cout << "1. create new file. \n"; cout << "2. read file. \n"; cout << "3. rechange file. \n"; cout << "4. update file. \n"; cout << "0. exit \n"; cin >> X; cout << "\n===========\n"; switch (X) { case 1: file_create(PATH); break; case 2: file_read(PATH); break; case 3: file_change(PATH); break; case 4: file_update(PATH); break; default: cout << "\n===========\n"; return false; } cout << "\n===========\n"; return true; } int main() { const char* PATH = "C:\\MyFiles\\4.txt"; while (menu(PATH)); cin.get(); cin.get(); cout << sizeof(uint8_t) << '\n'; } |
И не забывайте читать учебники!
почему в первом аргументе write или read идет такое выражение: (char*)&переменная ?? почему не просто переменная?
Наверное, потому что в зависимости от системы просто указатель может транслироваться как в число, так и в символ.
Лично я без понятия, почему обязательно приводить адрес к Си-строке.
&переменная — это указатель.
Синтаксис пришёл из языка С. Функции read и write написаны так, что первым параметром им требуется указатель. А коли обычная переменная не может быть указателем, когда она не аргумент-неуказатель, то есть есть как есть и нужно отдавать функции указатель на char.
а когда читаешь с одного файла в режиме binary и записываешь в другой файл в режиме binary, то визуально в текстовом файле должен быть текст или иероглифы?
Не понятен вопрос. Если читаешь то, что записано в текстовом режиме, и потом записываешь это в другой фай, то будет видно как текст.
если читать и записывать все в бинарном режиме (с флагом ios::binary) с текстового файла в пустой, то во втором файле будет виден текст?
Как записано, так и будет видно.
Вот пример: первоначально запись идёт в текстовом режиме, потом записанный в текстовом режиме файл читается в бинарном режиме и в бинарном режиме записывается. Поскольку первичный файл был записан в текстовом режиме, то и конечный результат видно как обычный текст, а не как бинарный файл.
спс, понял что будет виден текст