Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.79/57: Рейтинг темы: голосов - 57, средняя оценка - 4.79
oinari
5 / 4 / 0
Регистрация: 18.10.2009
Сообщений: 69
1

Чтение из файла с конца

22.05.2010, 12:50. Просмотров 10445. Ответов 14
Метки нет (Все метки)

Добрый день, не могу реализовать такую штуку =)
Хотелось бы имеющийся текстовый файл перезаписать с обратном порядке (все символы наоборот)
Понятно, что надо открыть файл на чтение и установить ук-ль на конец файла. А дальше...
Может циклом while читать посимвольно, но какое условие задать? =)
C++
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
//------------------------------------------
#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;
const char * my_file = "My_file.txt";
int input_f();
//------------------------------------------
int main()
{
    input_f();
    return 0;
}
//------------------------------------------
int input_f()
{
    ifstream fin;
    fin.open(my_file, ios_base::in | ios_base::ate); //открыть файл для чтения и поместить указатель в конец файла
    if (!fin) cerr << "File not found!";
    
    
    fin.close();
    cout << "\ndone!";
    return 0;
}
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
22.05.2010, 12:50
Ответы с готовыми решениями:

Чтение файла с несколькими знаками конца файла
В файле несколько раз встречается ноль, и ни как не получается прочитать его полностью. Как можно...

Чтение запросов до конца файла
Доброго времени суток, Помогите начинающему...Имеется задача.Само условие говорить не буду(не...

Чтение начиная с конца файла
Всем добрый вечер! Программа создает самопальный класс список как в STL и пишет/ читает с файла ...

Чтение файла с n строки и до конца файла
как сделать так чтобы писало не с начала файла а например с середины и до конца? fstream...

Чтение чисел из файла до конца строки
Есть один файл. В первой строке написано общее количество последующих строк, во всех остальных —...

14
Mur3ik
102 / 102 / 23
Регистрация: 12.05.2010
Сообщений: 232
22.05.2010, 13:20 2
зачем себе так усложнять жизнь?
читаешь весь файл построчной fgets(массив, размер можно, указатель на файл) в двухмерный динамический массив.... потом каждую строку разворачиваешь char *strrev(char *s); и начиная с последней строки пишешь в новый файл.

C++
1
2
3
4
5
6
7
8
9
10
11
char **arr = new char *[количество строк]; //создаем 2хмерный массив
for(int i=0;i<количества_строк, i++)//создаем 2хмерный массив
{
arr[i]=new char [размер строки];//создаем 2хмерный массив
}
int i=0;
while(!feof(pfile))//читаем из файла...
{
fgets(arr[i],255,pfile);
i++;
}
если надо будет, вечером смогу подробнее написать.
PS количество строк можно узнать прогнав fgets в цикле с счетчиком до создания массива.
1
oinari
5 / 4 / 0
Регистрация: 18.10.2009
Сообщений: 69
22.05.2010, 14:20  [ТС] 3
Комплируется нормально, работу прекращает во время выполнения, ошибка думаю происходит в fgets, как исправить не знаю.
C++
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
//------------------------------------------
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <stdio.h> 
#define MAXLIN 80
using namespace std;
const char * my_file = "My_file.txt";
//------------------------------------------
int main()
{
    FILE * f1;
    int n=0;
    char string [MAXLIN];
    if (0==(f1=fopen(my_file, "r"))) cerr << "File not found!"; //открытиена чтение
    while(fgets(string,MAXLIN,f1))  //счётчик строк в файле   
        n++;
    cout << n;
    //------------------------------------------
    char **arr = new char *[n]; //создаем 2хмерный массив
    //------------------------------------------
    for(int i=0;i<n;i++)//создаем 2хмерный массив
    {
        arr[i]=new char [MAXLIN];//создаем 2хмерный массив
    }
    //------------------------------------------
    int i=0;
    while(!feof(f1))//читаем из файла...
        {
            fgets(arr[i],MAXLIN,f1);
            i++;
        }
    //------------------------------------------
    //потом каждую строку разворачиваешь char *strrev(char *s); и начиная с последней строки пишешь в новый файл.
    for(int i=0;i<n;i++)
        arr[i]=strrev(arr[i]);
    //------------------------------------------
    for(int i=n;i!=0;i--)
        fputs(arr[i],f1);
    return 0;
}
//------------------------------------------
0
Mur3ik
102 / 102 / 23
Регистрация: 12.05.2010
Сообщений: 232
22.05.2010, 16:18 4
после того как ты посчитал строки нужно закрыть указатель на файл, и открыть заново, т.к. там указатель стоит в конце файла...

Добавлено через 13 минут
C++
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
#include <iostream>
#include <fstream>
#include <stdio.h> 
#define MAXLIN 80
using namespace std;
const char * my_file = "My_file.txt";
//------------------------------------------
int main()
{
        FILE * f1, *f2, *f3;
        int n=0;
        char string [MAXLIN];
        if (0==(f1=fopen(my_file, "r"))) cerr << "File not found!"; //открытиена чтение
        while(fgets(string,MAXLIN,f1))  //счётчик строк в файле 
                n++;
        cout << n;
        //------------------------------------------
        char **arr = new char *[n]; //создаем 2хмерный массив
        //------------------------------------------
        for(int i=0;i<n;i++)//создаем 2хмерный массив
        {
                arr[i]=new char [MAXLIN];//создаем 2хмерный массив
        }
        fclose(f1);
        //------------------------------------------
        if (0==(f2=fopen(my_file, "r"))) cerr << "File not found!";
        int i=0;
        while(!feof(f2))//читаем из файла...
                {
                        fgets(arr[i],MAXLIN,f2);
                        i++;
                }
        fclose(f2);
        //------------------------------------------
        //потом каждую строку разворачиваешь char *strrev(char *s); и начиная с последней строки пишешь в новый файл.
        if (0==(f3=fopen("new_file.txt", "w"))) cerr << "File not found!";
        for(int i=0;i<n;i++)
                arr[i]=strrev(arr[i]);
        //------------------------------------------
        for(int i=n-1;i>=0;i--)//т.к. нумерация в массиве с 0, то при i==0; должно выполняться, и из за того что нумерация с нуля... от количества строк отнимаем 1
                fputs(arr[i],f3);
        return 0;
}
1
22.05.2010, 16:18
oinari
5 / 4 / 0
Регистрация: 18.10.2009
Сообщений: 69
22.05.2010, 16:42  [ТС] 5
ААААА)))))))))) понял почему))) спасибо большое =)
п.с. тут сообщения удалять можно? оО
0
easybudda
Модератор
Эксперт JavaЭксперт CЭксперт С++
10621 / 6303 / 1582
Регистрация: 25.07.2009
Сообщений: 12,016
22.05.2010, 17:30 6
C
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
#include <stdio.h>
#include <stdlib.h>
 
#define FILE_NAME "simple.txt"
 
int main(void){
    char * buf, * p;
    long len;
    FILE * f;
 
    if ( ( f = fopen(FILE_NAME, "rb") ) == NULL ){
        perror("fopen");
        exit(EXIT_FAILURE);
    }
    if ( fseek(f, 0, SEEK_END) ){
        perror("fseek");
        exit(EXIT_FAILURE);
    }
    if ( ( len = ftell(f)) < 1 ){
        fprintf(stderr, "File can't be readen, or empty.\n");
        exit(EXIT_FAILURE);
    }
    rewind(f);
 
    if ( ( buf = (char*)malloc(len) ) == NULL ){
        perror("malloc");
        if ( fclose(f) )
            perror("fclose");
        exit(EXIT_FAILURE);
    }
 
    if ( fread(buf, 1, len, f) != len ){
        perror("fread");
        if ( fclose(f) )
            perror("fclose");
        exit(EXIT_FAILURE);
    }
    if ( fclose(f) )
        perror("fclose");
 
    for ( p = buf + len - 1; p >= buf; --p )
        putchar(*p);
 
    free(buf);
    exit(EXIT_SUCCESS);
}
0
odip
Эксперт С++
7169 / 3227 / 77
Регистрация: 17.06.2009
Сообщений: 14,166
23.05.2010, 10:02 7
Это все какие-то извращения
1) Определяем размер файла
2) Выделяем буфер
3) Читаем весь файл в память - одним read()
4) В памяти разворачиваем буфер

C
1
2
3
4
5
6
7
char *buf;
int buf_size;
char ch;
 
for ( i= 0, j= buf_size-1; i<j; i++, j-- ) {
    ch= buf[i]; buf[i]= buf[j]; buf[j]= ch;
}
5) Записываем в файл - одним write()
0
exbbrat
0 / 0 / 0
Регистрация: 27.03.2018
Сообщений: 10
22.10.2018, 12:40 8
А можешь подробнее написать с read() ?
0
COKPOWEHEU
1990 / 1215 / 273
Регистрация: 09.09.2017
Сообщений: 4,923
22.10.2018, 16:23 9
odip, Еще проще: отображаем файл на память и отображаем сразу там:
C
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
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <unistd.h>
#include <fcntl.h>
 
int main() {
  int fd;
  uint8_t *mem=NULL;
  size_t size, size2, i;
  
//отображаем файл на память
  fd = open("a.txt", O_RDWR, S_IRUSR);
  if(fd < 0)return -1;
  size = lseek(fd, 0, SEEK_END);
  mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if(mem == NULL){close(fd); return -2;}
  
//переворачиваем
  size2 = size/2;
  uint8_t temp;
  for(i=0; i<size2; i++){
    temp=mem[i]; mem[i]=mem[size-i-1]; mem[size-i-1]=temp;
  }
  
//закрываем
  munmap(mem, size);
  close(fd);
}
Добавлено через 6 минут
Вариант для мазохистов (WinAPI)
C
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
#include <windows.h>
#include <inttypes.h>
 
int main() {
  HANDLE fd, fm;
  uint8_t *mem=NULL;
  size_t size, size2, i;
  
  fd = CreateFile("a.txt",
                  GENERIC_READ | GENERIC_WRITE,
                  FILE_SHARE_READ | FILE_SHARE_WRITE,
                  NULL,
                  OPEN_EXISTING,
                  FILE_ATTRIBUTE_NORMAL,
                  NULL);
  if(fd == INVALID_HANDLE_VALUE)return -1;
  if(fd == NULL)return -2;
  size = SetFilePointer(fd, 0, NULL, FILE_END);
  fm = CreateFileMapping(fd, NULL, PAGE_READWRITE, 0, size, NULL);
  if(fm == NULL){
    CloseHandle(fm);
    return -3;
  }
  mem = MapViewOfFile(fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size);
  if(mem == NULL){
    CloseHandle(fm);
    CloseHandle(fd);
    return -4;
  }
  
  size2 = size/2;
  uint8_t temp;
  for(i=0; i<size2; i++){
    temp=mem[i]; mem[i]=mem[size-i-1]; mem[size-i-1]=temp;
  }
  
  UnmapViewOfFile(mem);
  CloseHandle(fm);
  CloseHandle(fd);
}
Добавлено через 2 часа 38 минут
Результаты тестирования простейшего решения в лоб (можно было бы поиграться с блочным чтением, но сейчас неохота) для трех вариантов: через потоки (open/read/write), через отображение на общую память (флаг MAP_SHARED) и через отображение на локальную память (флаг MAP_PRIVATE).
.
Файл ~600 МБ
потоки: 0.78 сек
shared: 0.56
private: 0.69
.
Файл ~4 ГБ
потоки: 17 сек
shared: 31
private: 21
.
В случае работы через потоки приходилось создавать массив размером с файл, то есть для сверхбольших файлов этот способ уже не подойдет. На маленьких файлах выигрывает отображение на память, вероятно за счет меньшего количества копирования туда-сюда. На крупных же лучше работает последовательное копирование в локальный буфер, а потом - не менее последовательное обратно. Произвольный же доступ вводит систему в ступор.
0
exbbrat
0 / 0 / 0
Регистрация: 27.03.2018
Сообщений: 10
22.10.2018, 22:07 10
Да но у меня простой файл,
но win10+ MSVisualStud15, не могу найти библиотеки
#include <sys/mman.h>
#include <unistd.h>
0
COKPOWEHEU
1990 / 1215 / 273
Регистрация: 09.09.2017
Сообщений: 4,923
23.10.2018, 10:10 11
exbbrat, что значит "простой файл"? Текстовый что ли?
Цитата Сообщение от exbbrat Посмотреть сообщение
но win10+ MSVisualStud15, не могу найти библиотеки
#include <sys/mman.h>
#include <unistd.h>
Это линуксовые. Виндовую версию я так и пометил, winAPI. Это второй листинг в моем предыдущем посте.
0
valen10
Параллельный Кот
1264 / 532 / 211
Регистрация: 25.03.2016
Сообщений: 1,186
Завершенные тесты: 1
23.10.2018, 14:17 12
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Вариант для мазохистов
Они оба для мазохистов, ибо стандартные потоки в C++ неплохо справляются с задачей.

Однако, никто не обратил внимания на то, что обрабатывать требуется текстовые файлы под Windows. Просто прочитать блок, перевернуть и записать обратно не получится, т.к.:

1. Конец строки в Windows состоит из двух байт CR+LF, если их поменять местами, получится чушь.
2. Если файл содержит многобайтовую кодировку, проблем еще больше.

В общем случае, придется преобразовать содержимое файла в кодировку, где все символы кодируются одинаковым количеством байт (например UTF-32), затем переставить их в обратном порядке и выполнить обратное преобразование и запись в файл.

Если же файл в кодировке Windows-1251 (допустима и UTF-8, но при условии, что файл содержит только символы из младшей половины таблицы, т.е. английские буквы, цифры, знаки препинания и еще некоторые символы), то можно обойтись и простым get().

C++
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
#include <iostream>
#include <fstream>
#include <string>
 
using namespace std;
 
int main() {
    string f_name = "input.txt";
 
    // Открыть на чтение/запись.
    fstream file(f_name, ios_base::in | ios_base::out);
 
    if (file.is_open()) {
 
        string s;
        char c;
 
        // Посимвольно прочитать весь файл.
        while (file.get(c)) {
            s += c;
        }
 
        // Выполнить перестановку символов в обратном порядке.
        for (size_t i = 0; i < s.size() / 2; i++) {
            swap(s[i], s[s.size() - i - 1]);
        }
 
        // Сбросить флаги состояния и вернуть указатель в начало файла.
        file.clear();
        file.seekg(0, ios_base::beg);
 
        // Записасть строку обратно в файл и закрыть его.
        file << s;
        file.close();
    }
 
    return 0;
}
Добавлено через 15 минут
Не посмотрел на дату. Некропостингом попахивает, брр...
0
COKPOWEHEU
1990 / 1215 / 273
Регистрация: 09.09.2017
Сообщений: 4,923
23.10.2018, 14:26 13
Цитата Сообщение от valen10 Посмотреть сообщение
Они оба для мазохистов, ибо стандартные потоки в C++ неплохо справляются с задачей.
А давайте не называть мазохистами тех, кто придумал отображать файлы на память.
Цитата Сообщение от valen10 Посмотреть сообщение
обрабатывать требуется текстовые файлы под Windows
Да ну?
Цитата Сообщение от oinari Посмотреть сообщение
Хотелось бы имеющийся текстовый файл перезаписать с обратном порядке (все символы наоборот)
Про win-специфичные ни слова, про кодировку тоже. Хотя с многобайтными кодировками задача будет поинтереснее. Впрочем, ее и уже решили до нас: tac a.txt | rev > b.txt
Цитата Сообщение от valen10 Посмотреть сообщение
В общем случае, придется преобразовать содержимое файла в кодировку, где все символы кодируются одинаковым количеством байт (например UTF-32), затем переставить их в обратном порядке и выполнить обратное преобразование и запись в файл.
Зачем такие сложности? Скажем, из первого байта utf-8 легко найти длину символа.
0
valen10
Параллельный Кот
1264 / 532 / 211
Регистрация: 25.03.2016
Сообщений: 1,186
Завершенные тесты: 1
23.10.2018, 20:44 14
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Про win-специфичные ни слова, про кодировку тоже.
В первом посте - да, но вопрос был поставлен в далёком 2010-м. exbbrat же говорит о win10 и ненайденных заголовках - похоже, у него Windows =) Дальше просто попытался обобщить, почему простая перестановка байт может не работать. Как минимум из-за двухбайтового конца строки.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Скажем, из первого байта utf-8 легко найти длину символа
Легко то легко, а поменять их местами? Или, как определить, какой из них первый, если читать последовательность с конца? При работе с текстом нет никакого желания этим заниматься. Многобайтовые кодировки для обработки преобразуют в более удобный вид. В python и Qt по крайней мере так, причем автоматически. Как там в rev не знаю, но можно посмотреть при желании, open source как никак.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
А давайте не называть мазохистами тех, кто придумал отображать файлы на память.
Это не о них, а тех, кто для решения простой задачи без конкретных требований по платформе/скорости использует платформозависимый API. Считаю, стандартная библиотека тут подходит больше.
0
COKPOWEHEU
1990 / 1215 / 273
Регистрация: 09.09.2017
Сообщений: 4,923
24.10.2018, 10:07 15
Цитата Сообщение от valen10 Посмотреть сообщение
Как минимум из-за двухбайтового конца строки.
Так win10 вроде научилась понимать однобайтный конец строки.
Цитата Сообщение от valen10 Посмотреть сообщение
Это не о них, а тех, кто для решения простой задачи без конкретных требований по платформе/скорости использует платформозависимый API. Считаю, стандартная библиотека тут подходит больше.
"дубовый" вариант с чтением сразу всего файла не сработает если файл не влезет в оперативку. В этом случае код отображения на память будет проще, хотя и дольше. Либо читать-писать кусками, что, конечно, эффективнее, но немного сложнее в программировании.
Цитата Сообщение от valen10 Посмотреть сообщение
Многобайтовые кодировки для обработки преобразуют в более удобный вид.
Что требует в худшем случае в 4 раза больше памяти.
0
24.10.2018, 10:07
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.10.2018, 10:07

Чтение до конца строки
В файле лежит только одно слово, мне его надо считывать while по символьно, я никак не разберусь с...

Чтение динамического массива с конца
Можно ли каким-то образом считывать динамический массив не с начала,а с конца?

Cin, чтение с конца полученного потока
Происходит ввод с клавиатуры последовательности чисел разделенных пробелами, нужно извлечь из этого...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.