C/UNIX mmap массив int
Это возможно mmap
файл, полный целых чисел как массив целых чисел? Я имею в виду что-то вроде этого (что не работает)
данный файл tmp.in
1 2 15 1258
и подобный код к этому
int fd;
if ((fd = open("tmp.in", O_RDWR, 0666)) == -1) {
err(1, "open");
}
size_t size = 4 * sizeof(int);
int * map = (int *) mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Я хотел бы иметь возможность позвонить
printf("%d\n", map[2]+1);
с ожидаемым результатом
16
Я нашел отображение символов с помощью sscanf
для анализа целых чисел, но мне нужно иметь числа в массиве (и, возможно, изменить их и сохранить их, когда munmap
). Использование только функций POSIX и системных вызовов.
Я нашел здесь, что mmap читает устаревший массив целых чисел из файла, но мне нужно, чтобы файл оставался читаемым (поэтому нет двоичного представления). С помощью strtok
а также atoi
заставляет меня использовать другой массив, не так ли? В конце мне нужно будет скопировать мои данные обратно в map
,
Спасибо за помощь:)
2 ответа
Нет, mmap
дает вам автоматическое отображение файла в ваше адресное пространство как есть.
Это означает, что текстовый файл будет отображаться как символы, а не как массив целых чисел. Другими словами, 1 2 15 1258
будет отображаться (при условии кодирования ASCII и окончания строк UNIX) как:
0x31 0x20 0x32 0x20 0x31 0x35 0x20 0x31 0x32 0x35 0x38 0x10
Если вы хотите сохранить данные как текстовые в файле, но иметь двоичные данные в памяти, вам придется конвертировать их самостоятельно (в обоих направлениях).
Предполагая, что входным файлом является текстовый файл (не двоичный файл, который может иметь целое число или, в этом отношении, любые двоичные данные, записанные в него), ваш файл будет отображен как строка, длина которой равна размеру файла.
Как только эта строка отображается в памяти, вы можете получить доступ к отдельным персонажам с помощью указателей.
Я хотел бы иметь возможность вызывать printf("%d\n", map[2]+1);
карта [2] +1
Это будет просто увеличить значение ASCII символа.
Насколько я понимаю, вы хотите отобразить файл в память и изменить значения, как целые числа. Это невозможно, если файл является текстовым файлом.
Я предлагаю вам сопоставить файл в памяти, прочитать символы, выполнить синтаксический анализ (в вашем случае ищите пробелы) и изменить значения символов.
Вот пример кода для вас:
[root @ mohitsingh memoryMap] # cat sample.txt
12345
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define FILEPATH "./sample.txt"
#define NUMINTS (5)
#define FILESIZE (NUMINTS * sizeof(int))
int main(int argc, char *argv[])
{
int i;
int fd;
char *map; /* mmapped array of char */
fd = open(FILEPATH, O_RDWR);
if (fd == -1) {
perror("Error opening file for reading");
exit(EXIT_FAILURE);
}
map = mmap(0, FILESIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
close(fd);
perror("Error mmapping the file");
exit(EXIT_FAILURE);
}
/* Read the file char-by-char from the mmap
**/
for (i = 0; i <NUMINTS; ++i) {
printf("%d: %c\n", i, map[i]);
}
/*change the character value
*Implement your own logic here to change the values as integer
*/
map[2]='9';
if (munmap(map, FILESIZE) == -1) {
perror("Error un-mmapping the file");
}
close(fd);
return 0;
}
[root @ mohitsingh memoryMap] # gcc test.c
[root @ mohitsingh memoryMap] #./a.out
0: 1
1: 2
2: 3
3: 4
4: 5
[root @ mohitsingh memoryMap] # cat sample.txt
12945