سؤال

Is it possible to mmap file full of integeres as integer array? I mean sth like this (which doesn't work)

given file tmp.in

1 2 15 1258

and similar code to this

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);

I'd like to be able call

printf("%d\n", map[2]+1);

with expected result

16

I found char mapping using sscanf to parse integers, but I need to have numbers in array (and possibly change them and have them saved when munmap). Using only POSIX functions and syscalls.

I found sth here mmap reading stale array of integers from an file but I need file remain readable (so no binary representation). Using strtok and atoiforces me to use another array, doesn't it? At the end I would need to copy my data back to map.

Thanks for help :)

هل كانت مفيدة؟

المحلول 2

No, mmap gives you automatic mapping of the file into your address space as-is.

That means that a text file will be mapped as characters rather than an array of integers. In other words, 1 2 15 1258 will be mapped (assuming ASCII encoding and UNIX line endings) as:

0x31 0x20 0x32 0x20 0x31 0x35 0x20 0x31 0x32 0x35 0x38 0x10

If you want to keep the data as textual in the file yet have it binary in memory, you will have to convert it yourself (both directions).

نصائح أخرى

Assuming that the input file is text file(not a binary file which can have integer or for that matter any binary data written into it), you file will be mapped as a string having length equal to file-size.

Once this string is mapped into the memory, you can access the individual characters using pointers.

I'd like to be able call printf("%d\n", map[2]+1);

map[2]+1

This will be just increment the ASCII value of the character.

As per my understanding, you want to map the file into memory and change the values like integers. This is not possible as long as file is a text file.

What I'll suggest is that you map the file into memory, read the characters, do the parsing(in your case look for spaces) and change the character values.

Here's a sample code for you:

[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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top