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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Evgenii32rus
0 / 0 / 0
Регистрация: 18.06.2013
Сообщений: 33
#1

Cохранение очень большого массива в текстовый файл - C++

18.08.2014, 20:46. Просмотров 581. Ответов 14
Метки нет (Все метки)

Помогите пожалуйста. Мне требуется сохранить карту в своей игре в текстовый файл. Класс карты:
C++
1
2
3
4
5
6
7
8
9
10
11
class cMap
{
     public:
          cRegion regions[100][100];
};
 
class cRegion
{
     public:
          int blocks[50][50][5];
};
Подскажите наиболее хороший способ.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.08.2014, 20:46
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Cохранение очень большого массива в текстовый файл (C++):

Тип данных для очень большого массива - C++
Есть массив где больше четырех миллионов элементов int massiv={0}; когда так пишу программа компилируется нормально но при...

Cохранение каталога в файл - C++
у меня есть каталог int age = {17,24}; я хочу его сохранить и пишу for(int i = 0;i < 2;i++) { ofstream file; ...

Дан текстовый файл, содержащий целые числа. Определить в каждой четной строке максимальное число и записать результаты в новый текстовый файл - C++
Дан текстовый файл, содержащий целые числа. Определить в каждой четной строке максимальное число и записать результаты в новый текстовый...

Сортировка очень большого файла. - C++
вопрос таков: есть очень большой файл, его нужно отсортировать. Так как файл большой его нужно извлекать по частям. Как это можно...

Текстовый файл UTF-8 сохранить как текстовый файл ANSI - C++
Есть текстовый файл в UTF-8 Нужно рядом сохранить его же, но в ANSI Как сделать это средствами c++? Среда Visual Studio 2010 ...

Сброс массива char в текстовый файл - C++
Я правильно понимаю, что для этого надо сделать массив на один символ длиннее, чем строка, и вписать последним символом '\0'? Вот моя...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
dimabubyakin
159 / 124 / 44
Регистрация: 16.10.2013
Сообщений: 1,738
Завершенные тесты: 5
18.08.2014, 20:55 #2
Evgenii32rus, хм.. а чем вас обычная запись в файл не устраивает?
К примеру в двоичный затолкать...
Vaiz
104 / 98 / 30
Регистрация: 01.07.2012
Сообщений: 277
Завершенные тесты: 1
18.08.2014, 20:56 #3
Evgenii32rus, мне кажется тут ничего особого не придумаешь, хранить как обычный массив. Если размер не постоянный, то первые числа в файле - размер массива.
AlexVRud
442 / 152 / 38
Регистрация: 04.07.2014
Сообщений: 431
18.08.2014, 21:05 #4
Сохранение больших массивов чисел в текстовый файл - плохая идея, особенно если это float/double. Мало того, что требуется много времени на преобразование числа в строку и обратно, так ещё тебе никто не гарантирует, что ты получишь тоже число. Для таких задач есть тот же BSON

Добавлено через 3 минуты
З.Ы.: Нашёл в загашниках ссылочку http://leopard.in.ua/2013/10/13/bina...ation-formats/
Evgenii32rus
0 / 0 / 0
Регистрация: 18.06.2013
Сообщений: 33
18.08.2014, 21:18  [ТС] #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
void SaveMap(cMap& Map)
{
    for(int i = 0; i < 100; i++)
    {
        for(int j = 0; j < 100; j++)
        {
             SaveRegion(Map.regions[i][j], i, j);
        }
    }
}
 
void SaveRegion(cRegion& Region, int x, int y)
{
    for(int i = 0; i < 50; i++)
    {
        for(int j = 0; j < 50; j++)
        {
              for(int k = 0; k < 5; k++)
              {
                    char xPos[3];
                    char yPos[3];
                    wsprintf(xPos, "%d", x);
                    wsprintf(yPos, "%d", y);
                    string fileName;
                    fileName.append(xPos); fileName.append("_"); fileName.append(yPos); fileName.append(".txt");
                    FILE* file;
                    file = fopen(fileName.data(), "w");
                    fwrite((void*)&Region.blocks[i][j][k], sizeof(int), 1, file);
                    fclose(file);
              }
        }
    }
}
Но в файл записываются только непонятные символы.
Vaiz
104 / 98 / 30
Регистрация: 01.07.2012
Сообщений: 277
Завершенные тесты: 1
18.08.2014, 21:45 #6
Цитата Сообщение от AlexVRud Посмотреть сообщение
Сохранение больших массивов чисел в текстовый файл - плохая идея, особенно если это float/double. Мало того, что требуется много времени на преобразование числа в строку и обратно, так ещё тебе никто не гарантирует, что ты получишь тоже число. Для таких задач есть тот же BSON
Добавлено через 3 минуты
З.Ы.: Нашёл в загашниках ссылочку http://leopard.in.ua/2013/10/13/bina...ation-formats/
А как организовывать логику: самостоятельно все прописывать или уже есть готовые библиотеки?

Добавлено через 6 минут
C++
1
2
3
file = fopen(fileName.data(), "w");
fwrite((void*)&Region.blocks[i][j][k], sizeof(int), 1, file);
fclose(file);
fwrite как раз вроде записывает в бинарном виде. Ну и фрагмент выше наверное был бы правильнее в таком виде без цикла по k.
C++
1
2
3
file = fopen(fileName.data(), "w");
fwrite((void*)Region.blocks[i][j], sizeof(int), 5, file);
fclose(file);
Добавлено через 4 минуты
И чуть не забыл, открывайте файл один раз до начала всех циклов, а то мне кажется у вас он каждый раз заново создается и все прошлое содержимое стирается. Или уж открывайте в режиме "a", а не "w"

Добавлено через 9 минут
А вообще наверное вы хотели что-то вроде такого.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void SaveRegion(cRegion& Region, int x, int y)
{
    char xPos[3];
    char yPos[3];
    wsprintf(xPos, "%d", x);
    wsprintf(yPos, "%d", y);
    string fileName;
    fileName.append(xPos); fileName.append("_"); fileName.append(yPos); fileName.append(".txt");    
    FILE* file;
    file = fopen(fileName.data(), "w");
    for(int i = 0; i < 50; i++)
    {
        for(int j = 0; j < 50; j++)
        {
              for(int k = 0; k < 5; k++)
              {
                    fprintf(file, "%d ",Region.blocks[i][j][k]);
              }
              fprintf(file, "\n");
        }
    }
    fclose(file);
}
AlexVRud
442 / 152 / 38
Регистрация: 04.07.2014
Сообщений: 431
18.08.2014, 21:59 #7
Цитата Сообщение от Vaiz Посмотреть сообщение
fwrite((void*)&Region.blocks[i][j][k], sizeof(int), 1, file)
И тут у тебя большой подводный камень. Размер int зависит от компилятора, ОС и её разрядности.

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

Ну а если хочется именно текстовый файл, то используй stringstream, для оптимизации записи.
Evgenii32rus
0 / 0 / 0
Регистрация: 18.06.2013
Сообщений: 33
19.08.2014, 19:29  [ТС] #8
Почему при выполнении этого кода возникает ошибка?
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
void SaveWorld(d3dFrameWork FrameWork, cMap Map)
{
    for(int i = 0; i < 50; i++)
    {
        for(int j = 0; j < 50; j++)
        {
            SaveRegion(Map, i, j);
        }
    }
}
 
void SaveRegion(cMap Map, int x, int y)
{
    FILE* f;
    char xPos[3]; char yPos[3];
    wsprintf(xPos, "%d", x); wsprintf(yPos, "%d", y);
    std::string filename;
    filename.append("Res//data//"); filename.append(xPos); filename.append("_"); filename.append(yPos); filename.append(".txt");
    f = fopen(filename.data(), "w");
    for(int i = 0; i < 50; i++)
    {
        for(int j = 0; j < 50; j++)
        {
            for(int k = 0; k < 5; k++)
            {
                fprintf(f, "%d", Map.regions[x][y].blockLayers[i][j][k]);
                fprintf(f, "%s", ",");
            }
        }
    }
    fclose(f);
}
Миниатюры
Cохранение очень большого массива в текстовый файл  
Vaiz
104 / 98 / 30
Регистрация: 01.07.2012
Сообщений: 277
Завершенные тесты: 1
19.08.2014, 20:00 #9
Evgenii32rus, это похоже на выход за пределы массива, но так просто трудно сказать где это.
Попробуйте поймать на каких значениях [x][y][i][j][k] происходит вылет. Для начала во всех циклах можно поставить по 1, т.е. for(int i = 0; i < 1; i++)

Добавлено через 1 минуту
а вообще у вас наверно в файлах это видно, по крайней мере какой последний файл был создан.
Alex5
1052 / 715 / 105
Регистрация: 12.04.2010
Сообщений: 1,810
19.08.2014, 20:46 #10
Цитата Сообщение от Evgenii32rus Посмотреть сообщение
Но в файл записываются только непонятные символы.
Evgenii32rus, если написать
C++
1
2
    int d = 0x1234;
    fwrite((void*)&d, sizeof(int), 1, file);
то в файл будут выведены байты: 0x34 и 0x12. Т.е. содержимое памяти по адресу &d.

Добавлено через 2 минуты
Цитата Сообщение от Evgenii32rus Посмотреть сообщение
Почему при выполнении этого кода возникает ошибка?
Чтобы определить почему, стоит определить (с помощью отладчика), в какой строке возникает ошибка.
Evgenii32rus
0 / 0 / 0
Регистрация: 18.06.2013
Сообщений: 33
19.08.2014, 20:52  [ТС] #11
Если передовать объект Map по ссылке, то ошибки не вознекает, но в файл записываются беспорядочные числа.
C++
1
void SaveMap(cMap& Map)
Пробовал подставлять конкретное число вместо Map.regions[x][y].blockLayers[i][j][k]. Запись выполняется правильно.
Alex5
1052 / 715 / 105
Регистрация: 12.04.2010
Сообщений: 1,810
19.08.2014, 21:09 #12
Цитата Сообщение от Evgenii32rus Посмотреть сообщение
C++
1
void SaveWorld(d3dFrameWork FrameWork, cMap Map)
Evgenii32rus, какой размер у Вас имеет переменная Map ? Evgenii32rus, понятно ли Вам, в чём отличие таких функций?
C++
1
2
3
void f1(cMap a );
void f2(cMap& b );
void f3(cMap* p );
Добавлено через 16 минут
Цитата Сообщение от Evgenii32rus Посмотреть сообщение
в файл записываются беспорядочные числа
Evgenii32rus, как Вы определили, что числа - беспорядочные? Может быть, это и есть числа Map.regions[x][y].blockLayers[i][j][k]).

Цитата Сообщение от Evgenii32rus Посмотреть сообщение
Запись выполняется правильно
orange_fox
34 / 34 / 6
Регистрация: 06.04.2014
Сообщений: 189
19.08.2014, 23:46 #13
А можно как-то memcpy всего объекта "сделать" в бинарный файл?
gazlan
3131 / 1906 / 285
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
20.08.2014, 07:46 #14
WriteFile function

Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write. The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium it's 63.95 MB.
Evgenii32rus
0 / 0 / 0
Регистрация: 18.06.2013
Сообщений: 33
20.08.2014, 21:07  [ТС] #15
Этот код работает правильно:
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
bool SaveInteger(FILE* file, int num, bool needPoints)
{
    char cNum[4] = {0};
    wsprintf(cNum, "%d", num);
    if(fwrite((void*)cNum, sizeof(cNum), 1, file) > 0)
    {
        if(needPoints)
        {
            char p[2] = {"."};
            fwrite((void*)p, sizeof(p), 1, file);
        }
        return true;
    }
    else
    {
        return false;
    }
}
 
bool cMap::SaveWorld()
{
    for(int i = 0; i < 50; i++)
    {
        for(int j = 0; j < 50; j++)
        {
            FILE* file;
            std::string fileName;
            char xPos[3]; char yPos[3];
            wsprintf(xPos, "%d", i); wsprintf(yPos, "%d", j);
            fileName.append("data//"); fileName.append(xPos); fileName.append("_"); fileName.append(yPos), fileName.append(".txt");
            file = fopen(fileName.data(), "w");
 
            for(int i2 = 0; i2 < 50; i2++)
            {
                for(int j2= 0; j2 < 50; j2++)
                {
                    for(int k2 = 0; k2 < 5; k2++)
                    {
                        int id = regions[i][j].blockLayers[i2][j2][k2];
                        if(!SaveInteger(file, id, true))
                        {
                            return false;
                        }
                    }
                }
                }
 
                        fclose(file);
            }
       }
 
return true;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.08.2014, 21:07
Привет! Вот еще темы с ответами:

Класс очень большого числа. Перегрузка operator++ - C++
Число хранится в массиве. Не могу сделать перегрузку ++. Помогите. byte* massiv; massiv = new byte; Big* operator++() {...

Копирование в текстовый файл из потока fstream массива типа char - C++
Всем привет! У меня довольно простой, но очень важный для меня вопрос, ответ на который пока не очевиден... Если я средствами Windows...

Дано число k (< 10) и текстовый файл, содержащий более k строк. Создать новый текстовый файл, содержащий k последних строк исходного файла - C++
Дано число k (&lt; 10) и текстовый файл, содержащий более k строк. Создать новый текстовый файл, содержащий k последних строк исходного...

Файл: Скопировать текст в другой текстовый файл файл, но чётные строки должны быть с большой буквы... - C++
Создать текстовый файл. Скопировать текст в другой текстовый файл файл, но чётные строки должны быть с большой буквы, а нечетные с...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
20.08.2014, 21:07
Ответ Создать тему
Опции темы

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