Форум программистов, компьютерный форум CyberForum.ru

Файловый ввод/вывод - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 39, средняя оценка - 4.85
Ольга_1993
0 / 0 / 0
Регистрация: 09.02.2011
Сообщений: 25
09.02.2011, 17:43     Файловый ввод/вывод #1
Ребят, не могу никак понять файловый ввод вывод текстовой информации в с++. Знаю сто открытие через fopen, а как создать сам текстовый файл в самой с++, а потом его считать?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.02.2011, 17:43     Файловый ввод/вывод
Посмотрите здесь:

C++ Файловый ввод-вывод.
Файловый ввод-вывод C++
Файловый ввод и вывод на С++ C++
Файловый ввод\вывод C++
Файловый ввод-вывод C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
09.02.2011, 18:24     Файловый ввод/вывод #2
Давайте определимся, что вы хотите: C или C++. fopen() - это функция C. Прототип выглядит так:

C
1
FILE * fopen ( const char * filename, const char * mode );
filename - имя файла
mode - режим. Выглядит как C-строка (массив char с нуль-терминатором в конце). Может иметь значения:
"r"Чтение. Файл должен существовать.
"w"Запись с перезаписью. Если файл не существует, он создаётся.
"a"Запись с дописыванием в конец. Если файл не существует, он создаётся.
"r+"Чтение-запись. Файл должен существовать.
"w+"Чтение-запись с перезаписью. Если файл не существует, он создаётся.
"a+"Чтение-запись с дописыванием в конец. Если файл не существует, он создаётся.

Чтение в стиле C:

C
1
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
Чтение из stream элементов данных в количестве не более nmemb (каждый размером в size байт) в область памяти, указанную ptr;

Запись в стиле C:

C
1
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
Запись в stream элементов данных в количестве nmemb (каждый размером в size байт) из области памяти, указанной ptr;

Обе функции возвращают количество записанных данных.

Вот пример программы (используя вызовы C):

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
47
#include <stdio.h>
 
void write( const char * fileName );
void read( const char * fileName );
 
int main()
{
    write( "test_file.txt" );
    read( "test_file.txt" );
 
    return 0;
}
 
void write( const char * fileName )
{
    const char * data = "Hello, world!"; //14 байт (учитывая 0x00 в конце)
    FILE * myFile = fopen( fileName, "w" );
 
    if( myFile == 0 )
    {
       printf( "Error opening %s for writing.\n", fileName );
       return;
    }
 
    int wrote = fwrite( data, sizeof(char), 14, myFile );
    printf( "Wrote %i bytes\n", wrote );
 
    fclose( myFile );
}
 
void read( const char * fileName )
{
    char data[255] = {0};
 
    FILE * myFile = fopen( fileName, "r" );
 
    if( myFile == 0 )
    {
       printf( "Error opening %s for reading.\n", fileName );
       return;
    }
 
    int read = fread( data, sizeof(char), 254, myFile );
    printf( "Read %i bytes:\n%s\n", read, data );
 
    fclose( myFile );
}
C-компилятор может не компилировать, я использовал C++-компиллер.

Но если вы хотите C++, используйте потоки файлового вывода-вывода (ifstream - ввод, ofstream - вывод, fstream - ввод и вывод). Подробнее тут: Чем отличается fstream от ofstream?

Удачи.
WinstonCherchil
 Аватар для WinstonCherchil
7 / 7 / 0
Регистрация: 20.01.2011
Сообщений: 73
09.02.2011, 23:03     Файловый ввод/вывод #3
Хорошо написал. Спасибо.
half-node
21 / 18 / 3
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 04:01     Файловый ввод/вывод #4
Подниму тему, дабы не плодить.
Разбираюсь в потоках.
Объясните пожалуйста, что не так в фукции read()?
write() пишет в файл все на ура. По крайней мере, размер файла соответствует тому, сколько объектов в него записано.
А вот чтение не проходит. Прям беда. Притом ошибка происходит уже после выполнения if(inFile.eof())
код, собственно:
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
void Distance::write()
{
    ofstream outFile;
    outFile.open("DIST.DD", ios::trunc|ios::binary);
    if(!outFile)
    {cerr << "\nНевозможно открыть файл для записи данных.\n"; _getch(); exit(1);}
 
    for(int i=0; i<count; i++)
    {
        outFile.write((char*)(arrap[i]), sizeof(Distance));
    }
    if(!outFile)
    {cerr << "\nЗапись в файл невозможна.\n"; _getch(); exit(1);}
    outFile.close();
}
 
void Distance::read()
{
    ifstream inFile;
    inFile.open("DIST.DD", ios::binary);
    if(!inFile)
    {cerr << "\nНевозможно открыть файл для чтения данных.\n"; _getch(); exit(1);}
    int i=0;
    while(true)
    {
        arrap[i] = new Distance;
        inFile.read((char*)arrap[i], sizeof(Distance));
        if(inFile.eof())
            break;
        i++;
    }
    if(!inFile)
    {cerr << "\nНевозможно произвести чтение из файла.\n"; _getch(); exit(1);}
    inFile.close();
}
Уже даже не знаю что и думать. Где -то завис.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.02.2011, 11:36     Файловый ввод/вывод #5
Так работает:

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
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
#include <iostream>
#include <fstream>
#include <string.h>
 
using namespace std;
 
const int count = 15;
 
struct Distance
{
    int x, y;
}
* arrap[ count ];
 
 
void write()
{
    ofstream outFile;
    outFile.open("DIST.DD", ios::trunc|ios::binary);
    if(!outFile)
    {
        cerr << "\nCould not open for writing.\n";
        return;
    }
 
    for(int i=0; i<count; i++)
    {
            outFile.write((char*)(arrap[i]), sizeof(Distance));
    }
 
    if(!outFile)
    {
        cerr << "\nWrighting is impossible.\n";
        return;
    }
    outFile.close();
 
}
 
void read()
{
    ifstream inFile;
    inFile.open("DIST.DD", ios::binary);
 
    if(!inFile)
    {
        cerr << "\nCould not open for reading.\n";
        return;
    }
 
    int i=0;
    while(true) //тут бы так: while( i < count ), иначе рискуете схватить переполнение буфера.
    {
            arrap[i] = new Distance;
            memset( arrap[i], 0, sizeof(Distance) ); //если не прочитает - значения x и y будут == 0
            inFile.read((char*)arrap[i], sizeof(Distance));
 
            if(inFile.eof())
                break;
 
            i++;
    }
    if(!inFile)
    {
        cerr << "\nReading is impossible.\n";
        return;
    }
 
    inFile.close();
}
 
int main()
{
    for( int i = 0; i < count; i++ )
    {
        arrap[i] = new Distance;
        arrap[i]->x = 5; //инициализировать заведомо известными числами
        arrap[i]->y = 8; //инициализировать заведомо известными числами
    }
 
    write();
 
    for( int i = 0; i < count; i++ )
    {
        delete [] arrap[i];
    }
 
    read();
 
    cout << "\n-- Read data: ---------------------\n";
 
    for( int i = 0; i < count; i++ )
    {
        cout << arrap[i]->x << ';' << arrap[i]->y;
 
        if( arrap[i]->x == 5 && arrap[i]->y == 8 )
           cout << " - OK" << endl;
        else
           cout << " - FAIL" << endl;
 
        delete [] arrap[i];
    }
}
Ваша ошибка в том, что вы проверяете ( !inFile ). inFile будет == false в том числе, если установлен eof-bit. Открыт файл, или нет, проверяют с помощью ( inFile.is_open() == true )
4ance
1 / 1 / 0
Регистрация: 02.11.2010
Сообщений: 78
11.02.2011, 11:59     Файловый ввод/вывод #6
Цитата Сообщение от WinstonCherchil Посмотреть сообщение
Хорошо написал. Спасибо.
присоединяюсь.
Файлы ещё не проходил, поэтому сразу сохранил себе этот пост
half-node
21 / 18 / 3
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 15:07     Файловый ввод/вывод #7
Цитата Сообщение от talis Посмотреть сообщение
Ваша ошибка в том, что вы проверяете ( !inFile ). inFile будет == false в том числе, если установлен eof-bit. Открыт файл, или нет, проверяют с помощью ( inFile.is_open() == true )
Спасибо большое! Почерпнул новой информации от Вас.
Но вот, крутил-крутил головой. В методе read(), фактически, ничего не поменялось, кроме дополнительного метода при чтении. (отдельное спасибо за него.) Почему же работает тогда? Я имею в виду, что такого поменялось, что код непосредственно чтения не изменился, но стал работать?
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.02.2011, 15:13     Файловый ввод/вывод #8
Да, собственно, ничего. Вы писали:

C++
1
2
3
4
5
6
7
8
if(!inFile)
{
    cerr << "\nНевозможно произвести чтение из файла.\n";
    _getch();
    exit(1); //это завершало программу преждевременно. Я просто вернул из функции.
               //кроме того, вторая такая проверка после цикла чтения (как и после цикла записи) избыточна
               //и не имеет смысла.
}
Старайтесь не пользоваться функцией exit(); Её часто применяют в игрушках. Знаете, когда игра вылетает без объяснений на середине сохранения, и пол-вечера игры псу под хвост? Вот это, скорее всего, оно. Когда винда прерывает игру - вы видите "Отправить отчёт - Не отправлять отчёт", а это именно игрушка вылетает. В функциях, в которых возможна ошибка - старайтесь возвращать либо bool (успешно/не успешно), либо int с кодом конкретной ошибки. Тогда вы сможете судить о том, что пошло не так, а не просто вылетать.
half-node
21 / 18 / 3
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 15:23     Файловый ввод/вывод #9
В общем я так понял, чтобы наверняка, нужно для начала вычислить (если файлу открывается уже после нового запуска программы, что обнуляет count), сколько объектов класса записано в файл. И делать цикл i<count
Иначе ничего не получается.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.02.2011, 15:30     Файловый ввод/вывод #10
Да, так и нужно делать. Но не то, чтобы не получится... Понимаете, если вы например выделили память под массив из 5 int'ов - это 5 * 4 = 20 байт:

00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00 | 00 00 00 00

И начали их читать, но прочитали 6 int'ов:

00 00 00 40 | 00 00 80 1A | 7F FF FF FF | F0 00 0A 13 | DE AD BE EF | 00 00 40 0D

Вы вылезете за пределы массива. Компилятор вам ничего не скажет. Вы либо схватите ошибку сегментации памяти - SEGFAULT, либо затрёте какую-то информацию, которая была на месте 5'го int'а.

Поэтому нужно точно знать, сколько байт вам нужно.
half-node
21 / 18 / 3
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 16:00     Файловый ввод/вывод #11
В общем, я даже не знаю что делать.
1 - записываю три объекта в файл. Каждый объект занимает 8 байт (4 инт, 4 флоат)
2 - на выходе получаю файл размером 24 байта.
3 - при чтении, проверяю, сколько объектов записано в файл и считываю их в цикле.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Distance::read()
{
    ifstream inFile;
    inFile.open("DIST.DD", ios::in|ios::binary);
    if(!inFile)
    {cerr << "\nНевозможно открыть файл для чтения данных.\n"; return;}
    inFile.seekg(0,ios::end);
    int endpos = inFile.tellg();
    int num = endpos/sizeof(Distance);
    cout << "\nИдет чтение " << num << " записей.\n";
    for(int i=0; i<num; i++)
    {
        arrap[i] = new Distance;
        memset( arrap[i], 0, sizeof(Distance) );
        inFile.read((char*)arrap[i], sizeof(Distance));
    }
    if(!inFile)
    {cerr << "\nНевозможно произвести чтение из файла.\n"; return;}
    inFile.close();
}
Итог - "Невозможно произвести чтение из файла."
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.02.2011, 16:04     Файловый ввод/вывод #12
Ну правильно. Зачем-то после цикла считывания вы проверяете
C++
1
2
3
if(!inFile)
        {cerr << "\nНевозможно произвести чтение из файла.\n"; return;}
        inFile.close();
Во-первых, скажите зачем? Во-вторых, в конце чтения вы упираетесь в конец файла и выставляется бит eof (end-of-file). Проверка !inFile выполняется и вам выводится сообщение "Невозможно произвести чтение из файла". Уберите эту проверку вообще, она там не нужна. Лучше проверьте, что вы прочитали - скорее всего, данные будут верны.
half-node
21 / 18 / 3
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 16:10     Файловый ввод/вывод #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
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// 12_1.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <fstream>
#include <process.h>
#include <windows.h>
using namespace std;    
 
const int MAXARR = 100;
 
 
class Distance
{
private:
    int feet;
    float inches;
    static int count;
    static Distance* arrap[];
public:
    void getdata()
    {
        cin.ignore(10,'\n');
        cout << "Введите футы: "; cin >> feet;
        cout << "Введите дюймы: "; cin >> inches;
    }
 
        void putdata()
    {
        cout << "Feets: " << feet;
        cout << "Inches: " << inches;
    }
 
    static void add();
    static void write();
    static void read();
    static void display();
};
 
int Distance::count=0;
Distance* Distance::arrap[MAXARR];
 
 
void Distance::add()
{
    arrap[count] = new Distance;
    arrap[count++]->getdata();
}
 
void Distance::write()
{
    ofstream outFile;
    outFile.open("DIST.DD", ios::trunc|ios::binary);
    if(!outFile)
    {cerr << "\nНевозможно открыть файл для записи данных.\n"; return;}
 
    for(int i=0; i<count; i++)
    {
        outFile.write((char*)(arrap[i]), sizeof(Distance));
    }
    if(!outFile)
    {cerr << "\nЗапись в файл невозможна.\n"; return;}
    outFile.close();
}
 
void Distance::read()
{
    ifstream inFile;
    inFile.open("DIST.DD", ios::in|ios::binary);
    if(!inFile)
    {cerr << "\nНевозможно открыть файл для чтения данных.\n"; return;}
    inFile.seekg(0,ios::end);
    int endpos = inFile.tellg();
    int num = endpos/sizeof(Distance);
    cout << "\nИдет чтение " << num << " записей.\n";
    for(int i=0; i<num; i++)
    {
        arrap[i] = new Distance;
        memset( arrap[i], 0, sizeof(Distance) );
        inFile.read((char*)arrap[i], sizeof(Distance));
    }
    //if(!inFile)
    //{cerr << "\nНевозможно произвести чтение из файла.\n"; return;}
    inFile.close();
}
 
void Distance::display()
{
    for(int i =0; i<count; i++)
        arrap[i]->putdata();
}
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    char choice;
    while(true)
    {
        cout << "\nЧто? a/w/r/d/x/p: ";
        cin >> choice;
        switch(choice)
        {
        case 'a':
            Distance::add(); break;
        case 'w':
            Distance::write(); break;
        case 'r':
            Distance::read(); break;
        case 'd':
            Distance::display(); break;
        case 'x':
            exit(0);
        default:
            cout << "Неверный атрибут.\n";
        }
    }
 
    _getch();
    return 0;
}
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.02.2011, 16:45     Файловый ввод/вывод #14
Зачем в class Distance ваше Distance* arrap[]; ? Вы в объекте типа Distance храните указатели на объекты типа Distance, которые хранят указатели на объекты типа Distance, которые хранят указатели на объекты типа Distance, которые хранят указатели на объекты типа Distance... Чего вы пытаетесь этим добиться?

Добавлено через 7 минут
Я бы сделал так:

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
47
48
49
50
51
52
53
54
55
56
class Distance
{
private:
        int feet;
        float inches;
public:
        void getdata()
        {
                cin.ignore(10,'\n');
                cout << "Введите футы: "; cin >> feet;
                cout << "Введите дюймы: "; cin >> inches;
        }
 
        void putdata()
        {
                cout << "Feets: " << feet;
                cout << "Inches: " << inches;
        }
 
        void setInches( float _inches ){ inches = _inches; };
        void setFeet( int _feet ){ feet = _feet ; };
 
        float getInches(){ return inches; };
        int getFeet(){ return feet; };
};
 
const int arrap_count;
Distance* arrap[ arrap_count ];
 
 
void write()
{
//...
   file.write( (char*)(arrap_count), sizeof(arrap_count) );
 
   for( int i = 0; i < arrap_count; i++ )
   {
      float inches = arrap[i]->getInches();
      int feet = arrap[i]->getFeet;
      file.write( (char*)(inches), sizeof(inches) );
      file.write( (char*)(feet), sizeof(feet) );
   }
//...
}
 
void read()
{
//...
   float inches
   int feet
   file.read( (char*)(inches), sizeof(inches) );
   file.read( (char*)(feet), sizeof(feet) );
   arrap[i]->setInches( inches );
   arrap[i]->setFeet( feet );
//...
}
Добавлено через 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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
class Distance
{
private:
        int feet;
        float inches;
public:
        Distance( int feet, float inches ){ setFeet( feet ); setInches( inches ); };
 
        void getdata()
        {
                cin.ignore(10,'\n');
                cout << "Введите футы: "; cin >> feet;
                cout << "Введите дюймы: "; cin >> inches;
        }
 
        void putdata()
        {
                cout << "Feets: " << feet;
                cout << "Inches: " << inches;
        }
 
        void setInches( float _inches ){ inches = _inches; };
        void setFeet( int _feet ){ feet = _feet ; };
 
        float getInches(){ return inches; };
        int getFeet(){ return feet; };
};
 
list<Distance>arrap;
 
void write()
{
//...
   file.write( (char*)(arrap.size), sizeof(arrap.size) );
 
   list<Distance>::iterator it = arrap.begin();
 
   for( int i = 0; i < arrap.size; i++ )
   {
      float inches = (*it)->getInches();
      int feet = (*it)->getFeet;
      file.write( (char*)(inches), sizeof(inches) );
      file.write( (char*)(feet), sizeof(feet) );
      it++;
   }
//...
}
 
void read()
{
   
//...
   int size;
   file.read( (char*)(size), sizeof(size) );
 
   arrap.clear();
 
   for( int i = 0; i < size; i++ )
   {
      float inches;
      int feet;
 
      file.read( (char*)(inches), sizeof(inches) );
      file.read( (char*)(feet), sizeof(feet) );
 
      Distance dist ( feet, inches );
      arrap.push_back( dist );
   }
//...
}
half-node
21 / 18 / 3
Регистрация: 12.08.2010
Сообщений: 206
11.02.2011, 17:01     Файловый ввод/вывод #15
Спасибо.
В Ваших случаях, для меня, пока-что много пробелов.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.02.2011, 03:42     Файловый ввод/вывод
Еще ссылки по теме:

C++ Файловый ввод / вывод
C++ Файловый ввод вывод
C++ Поменять консольный ввод-вывод на файловый ввод-вывод

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

Или воспользуйтесь поиском по форуму:
Ольга_1993
0 / 0 / 0
Регистрация: 09.02.2011
Сообщений: 25
13.02.2011, 03:42  [ТС]     Файловый ввод/вывод #16
Ребят, всем большое спасибо)))))))))))))
Yandex
Объявления
13.02.2011, 03:42     Файловый ввод/вывод
Ответ Создать тему
Опции темы

Текущее время: 00:12. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru