mmap читает устаревший массив целых чисел из файла

Я пытаюсь прочитать матрицу целых чисел из файла, используя mmap. Если я получаю его как указатель на символ из функции mmap, я вижу все правильно, но если я использую указатель int, это дает мне устаревшие данные. Проблема с использованием указателя на символ состоит в том, что мне нужно проанализировать всю строку, используя strtok или что-то еще, и получить целые числа один за другим. Размер моей матрицы будет 4k * 4k, поэтому многие вызовы sscanf и strtok неэффективны. Пожалуйста, посмотрите на программу и вывод

#define INTS 3 * 3

int main()
{

    FILE* in = fopen("int_file", "rb");
    int* ints = (int*)mmap(0, INTS * sizeof(int),
                      PROT_READ, MAP_FILE | MAP_PRIVATE, fileno(in),0);
    fclose(in);
    for(int i = 0; i < INTS; ++i) { 
        std::cout << ints[i] << std::endl;
    }
    munmap(ints, INTS * sizeof(int));
    return 0;
}

Содержимое int_file

510 20 30 40 50 60 100 200 10000

Выход

540029237 857747506 808716848 540030240 822751286 84097028

2 ответа

Решение

Значение ACSII текста печатается.

Ваш текст выглядит так:

510 20 30...

Из таблицы ASCII (чтобы объяснить, что я хочу сказать):

No.       ASCII (hex)

Space ->   20
0     ->   30
1     ->   31
2     ->   32
3     ->   33
5     ->   35

int является 4 байт по размеру, поэтому, беря первый 4 байт:

Преобразование в ASCII, "510 " дает "35 31 30 20" в памяти, которая 0x20303135 (540029237 как десятичное) для немного порядкового номера машины. Точно так же, следующий 4 байтов "20 3" дает 0x33203032(857747506 как десятичное число). Это то, что вы получаете.

В этом случае вам необходимо преобразовать каждый ACSII в целое число, используя atoi() или аналогичный.

Но вы можете хранить ваши целые числа как их двоичное значение, а не как ASCII. Файл не будет читаемым человеком, но он будет выполнять ваши задачи.

Читая это как int * возможно, если данные в файле хранятся из массива int или непрерывной памяти через calloc. Писатель должен выглядеть так,

#include <iostream>
#include <sys/mman.h>
#include <stdio.h>

using namespace std;

int inst[] = {510, 20, 30, 40, 50, 60, 100, 200, 10000 };

#define INTS 3 * 3

int main()
{
        FILE* out = fopen("int_file", "wb");  // Error checks are needed
        char *ptr = (char *) inst;
        fwrite( ptr, sizeof( int ), INTS, out );
        fclose( out);
        return 0;
}

Затем читатель может читать, используя mmap вроде как в вашем коде,

#include <iostream>
#include <sys/mman.h>
#include <stdio.h>

using namespace std;

#define INTS 3 * 3

int main()
{

    FILE* in = fopen("int_file", "rb");    // Error checks are needed
    int* ints = (int*)mmap(0, INTS * sizeof(int),
                    PROT_READ, MAP_FILE | MAP_PRIVATE, fileno(in),0);
    fclose(in);
    for(int i = 0; i < INTS; ++i) {
            std::cout << ints[i] << std::endl;
    }
    munmap(ints, INTS * sizeof(int));
    return 0;
}

Если не хранится из массива или непрерывной памяти, то с помощью char * а также strtok а также atoi это лучшее решение..

Другие вопросы по тегам