问题
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 atoi
forces me to use another array, doesn't it? At the end I would need to copy my data back to map
.
Thanks for help :)
回答1:
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).
回答2:
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
来源:https://stackoverflow.com/questions/21254270/c-unix-mmap-array-of-int