LINUX.ORG.RU

Чтение многомерного массива из отраженого файла


0

1

Здравствуйте. Ниже приведены программы записи и чтения одномерного массива из mmap файла. Как мне прочитать многомерный(трехмерный, например) массив данных из файла? Заранее спасибо.

WRITE

#define width 20
#define FILEPATH "/tmp/data.txt"
int main(int argc, char *argv[])
{
unsigned char Dekart[width];
int i;
for (i=0;i<width; i++)	Dekart[i] =(unsigned char)rand()%255;
int fd = open(FILEPATH, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); // дескриптор файла
int file_size = sizeof(Dekart);
lseek(fd, file_size+1, SEEK_SET); // перемещаемся в конец
write(fd, "\0", 1); // делаем запись
void* file_memory = mmap(NULL, file_size, PROT_WRITE, MAP_SHARED, fd, 0);// указатель на отображенный в памяти файл
close(fd);
memcpy(file_memory, Dekart, file_size); //копируем из Dekart в file_memory
munmap(file_memory, file_size);
}

READ

#define width 20
#define FILEPATH "/tmp/data.txt"

int main(int argc, char *argv[])
{
int i;
unsigned char *Dekart;
int fd = open(FILEPATH, O_RDWR, S_IRUSR|S_IWUSR);// открываем файл для чтения
if (fd<0)  printf ("%s\n", "У нас проблемы");
else
{
Dekart = mmap(0, sizeof(Dekart), PROT_READ, MAP_SHARED, fd, 0);// отображаем его содержимое в память и получаем указатель на него
close(fd);// освобождаем дескриптор
for (i=0;i<width; i++)	printf("%d\n", Dekart[i]);
}
}



Последнее исправление: Vitaly1988 (всего исправлений: 1)

Точно так же. Писать двумерный массив, как a[y][x] (т.е. построчно формировать линейный массив из двумерного). Аналогично из трех- и более мерного.

Eddy_Em ☆☆☆☆☆
()

Читать/писать/хранить одномерный массив, а индексы высчитывать вручную.

Для двумерного: arr[x + y * width]; для трёхмерного: arr[x + y * width + z * width * height].

schizoid ★★★
()
Ответ на: комментарий от schizoid

И да, размер этого одномерного массива будет (width * height * depth).

schizoid ★★★
()
Ответ на: комментарий от Eddy_Em

Так? WRITE

#define width 5
#define height 3
#define FILEPATH "/tmp/data.txt"
int main(int argc, char *argv[])
{
unsigned char Dekart[width][height];
int i,j;
for (i=0;i<width; i++)
for (j=0;j<height; j++)
{
	Dekart[i][j] =(unsigned char)rand()%255;
	printf("%d\n", Dekart[i][j] );
}
int fd = open(FILEPATH, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); // дескриптор файла
int file_size = sizeof(Dekart);
lseek(fd, file_size+1, SEEK_SET); // перемещаемся в конец
write(fd, "\0", 1); // делаем запись
void* file_memory = mmap(NULL, file_size, PROT_WRITE, MAP_SHARED, fd, 0);// указатель на отображенный в памяти файл
close(fd);
memcpy(file_memory, Dekart, file_size); //копируем из Dekart в file_memory
munmap(file_memory, file_size);
}
Тут вроде бы все нормально:

103 198 105 81 0 74 236 41 205 186 171 242 251 227

READ

#define width 5
#define height 3
#define FILEPATH "/tmp/data.txt"
int main(int argc, char *argv[])
{
int i,j;
unsigned char *Dekart[height];
int fd = open(FILEPATH, O_RDWR, S_IRUSR|S_IWUSR);// открываем файл для чтения
if (fd<0)  printf ("%s\n", "У нас проблемы");
else
{
for (j=0;j<height;j++)
Dekart[j] = mmap(0, width, PROT_READ, MAP_SHARED, fd, width*j);// отображаем его содержимое в память и получаем указатель на него
close(fd);// освобождаем дескриптор
for (i=0;i<width; i++)
 for (j=0;j<height; j++)
	printf("%d; %d; %d\n", i , j , Dekart[i][j]);
}
}
А тут все плохо:

0; 0; 103; 0; 1; 198; 0; 2; 105; Ошибка сегментирования

Vitaly1988
() автор топика
Ответ на: комментарий от Vitaly1988

Конечно, плохо: вначале у вас был массив Dekart[width][height], в котором данные по порядку следуют друг за другом, а затем вы сделали массив указателей *Dekart[height], что совершенно не то же самое.

Либо создавайте такой же массив Dekart[width][height], либо (т.к. скорее всего размеры массива будут динамическими) создавайте **Dekart, делайте ему malloc и malloc для каждого *Dekart, а затем в цикле заполняйте.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Vitaly1988

Отображай содержимое файла как структуру и будет тебе счастье.

Запись:

#define width 5
#define height 3
#define FILEPATH "/tmp/data.txt"

struct dekart {
    unsigned char values[width][height];
};

int main(int argc, char *argv[])
{
    int i, j;

    int fd = open(FILEPATH, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); // дескриптор файла
    int file_size = sizeof(struct dekart);
    lseek(fd, file_size + 1, SEEK_SET); // перемещаемся в конец
    write(fd, "\0", 1); // делаем запись
    struct dekart *file_memory = mmap(NULL, file_size, PROT_WRITE, MAP_SHARED, fd, 0);// указатель на отображенный в памяти файл
    close(fd);

    for (i=0;i<width; i++)
        for (j=0;j<height; j++)
        {
            file_memory->values[i][j] = (unsigned char)rand()%255;
            printf("[%d][%d] = %d\n", i, j, file_memory->values[i][j] );
        }

    munmap(file_memory, file_size);
    return 0;
}

Чтение:

#define width 5
#define height 3
#define FILEPATH "/tmp/data.txt"

struct dekart {
    unsigned char values[width][height];
};

int main(int argc, char *argv[])
{
    int i, j;

    int fd = open(FILEPATH, O_RDWR, S_IRUSR|S_IWUSR); // дескриптор файла
    int file_size = sizeof(struct dekart);
    struct dekart *file_memory = mmap(NULL, file_size, PROT_READ, MAP_SHARED, fd, 0);// указатель на отображенный в памяти файл
    close(fd);

    for (i=0;i<width; i++)
        for (j=0;j<height; j++)
        {
            printf("[%d][%d] = %d\n", i, j, file_memory->values[i][j] );
        }

    munmap(file_memory, file_size);
    return 0;
}

Deleted
()
Ответ на: комментарий от Deleted

Спасибо большое! Находил кучу примеров как отображать структуры, но никогда бы не догадался засунуть в нее матрицу)

Vitaly1988
() автор топика
Ответ на: комментарий от Deleted

Это если нужен указатель на элементы массива, что обычно понимается под «указателем на массив». А если нужен указатель на «массив размера height», то так:

unsigned char (*ptr)[height] = &file_memory->values[0];

Кстати такая конструкция помогает и вовсе без структуры обойтись.

Запись:

int main(int argc, char *argv[])
{
    int i, j;

    int fd = open(FILEPATH, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); // дескриптор файла
    int file_size = width * height;
    lseek(fd, file_size + 1, SEEK_SET); // перемещаемся в конец
    write(fd, "\0", 1); // делаем запись
    unsigned char (*file_memory)[height] = mmap(NULL, file_size, PROT_WRITE, MAP_SHARED, fd, 0);// указатель на отображенный в памяти файл
    close(fd);

    for (i=0;i<width; i++)
        for (j=0;j<height; j++)
        {
            file_memory[i][j] = (unsigned char)rand()%255;
            printf("[%d][%d] = %d\n", i, j, file_memory[i][j] );
        }

    munmap(file_memory, file_size);
    return 0;
}

Чтение:

int main(int argc, char *argv[])
{
    int i, j;

    int fd = open(FILEPATH, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); // дескриптор файла
    int file_size = width * height;
    unsigned char (*file_memory)[height] = mmap(NULL, file_size, PROT_READ, MAP_SHARED, fd, 0);// указатель на отображенный в памяти файл
    close(fd);

    for (i=0;i<width; i++)
        for (j=0;j<height; j++)
        {
            printf("[%d][%d] = %d\n", i, j, file_memory[i][j] );
        }

    munmap(file_memory, file_size);
    return 0;
}

Deleted
()
Ответ на: комментарий от Deleted

Спасибо! Все получилось именно так, как хотел.

Vitaly1988
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.