Передача файла данных с помощью cat в программу на C++

Мне нужна помощь в передаче файла (16-битные необработанные целые числа с прямым порядком байтов со знаком) из командной строки в мою программу:

cat data.dat | myprogram

Затем он должен преобразовать данные в 16-битные целые числа со знаком. Он работает для первых 12 значений. 13-е значение неверно, за ним следуют нули.

Вторая проблема заключается в том, что программа входит в цикл while только один раз.

Я использую Windows + MinGW.

Мой код:

#include <iostream>
using namespace std;

#define DEFAULT_BUF_LENGTH (16 * 16384)

int main(int argc, char* argv[]) 
{
    char buf[DEFAULT_BUF_LENGTH];

    while(cin >> buf) 
    {
        int16_t* data = (int16_t*) buf; //to int

        for(int i=0;i<18;i++)
        {
            cout << data[i] << endl;
        }
    }
    return 0;
}

Выход:

0
9621
-14633
-264
5565
-12288
9527
-7109
11710
6351
4096
-5033
5773
147
0
0
0
0

Спасибо за вашу помощь!


person fuxT    schedule 19.07.2015    source источник
comment
возможный дубликат конвейера для ввода/вывода   -  person Jared Burrows    schedule 19.07.2015
comment
Проверьте это обсуждение. В Windows стандартный ввод открывается в текстовом режиме, и определенный байт указывает на конец файла, решение состоит в том, чтобы повторно открыть его в двоичном режиме.   -  person dewaffled    schedule 19.07.2015
comment
Вы не можете использовать >>, он преобразует окончания строк. Вы должны использовать функции неформатированного ввода, такие как cin.read(). en.cppreference.com/w/cpp/io/basic_istream   -  person Galik    schedule 19.07.2015


Ответы (2)


Вы можете попробовать использовать read() вместо оператора >>, который обычно используется для форматированного ввода. Также полезно проверить, сколько данных было фактически прочитано:

#include <iostream>
using namespace std;

#define DEFAULT_BUF_LENGTH (16 * 16384)

int main(int argc, char* argv[]) 
{
    char buf[DEFAULT_BUF_LENGTH];

    for(;;) 
    {
        cin.read(buf, sizeof(buf));
        int size = cin.gcount();
        if (size == 0) break;

        int16_t* data = (int16_t*) buf; //to int

        for(int i=0;i<size/sizeof(int16_t);i++)
        {
            cout << hex << data[i] << endl;
        }
    }
    return 0;
}
person Alexander Balabin    schedule 19.07.2015
comment
Вторая проблема все еще существует, программа печатает только первые 12 значений. Я забыл упомянуть, что компилирую свои программы с помощью g++ myprogram.cpp -static -o myprogram. Возможно в этом причина? Если я скомпилирую свою программу без флага -static, она вылетит после выполнения (APPCRASH: имя модуля ошибки: libstdc++-6.dll). Я не нашел решения этой проблемы, но я думаю, что это как-то связано с 64-битной Windows. В Linux ваш код работает так, как ожидалось. - person fuxT; 21.07.2015
comment
Было бы полезно иметь ваш входной файл - person Alexander Balabin; 21.07.2015
comment
Даже простая программа helloworld.cpp падает, если я не устанавливаю флаг -static. Я думаю, что мой MinGW сломан. Моя проблема похожа на эту: Программа c helloworld, скомпилированная с помощью mingw, дает сбой с недопустимым аргументом%5d">stackoverflow.com/questions/18157464/, но в windows\syswow64 нет libstdc++.dll , который я мог бы удалить... - person fuxT; 21.07.2015
comment
Я загрузил для вас тестовый файл: filedropper.com/rawdata Вы также используете MinGW + 64-битную Windows? - person fuxT; 21.07.2015

Оператор cin >> buf не заполняет весь buf данными. Он читает только следующий «набор» непробельных символов. Изменить cin >> buf на read(0, buf, sizeof(buf)) > 0

Если вы настаиваете на использовании потоков C++, измените начало цикла на:

while (!cin.eof()) {
    cin.read(buf, sizeof(buf));
    [...]
person nsilent22    schedule 19.07.2015
comment
Я согласен с диагнозом; это проблема. Я не уверен, что предложенное средство является лучшим вариантом. Конечно, есть способы читать двоичные данные из cin вместо того, чтобы возвращаться к функциям файлового дескриптора POSIX, таким как read(), для которых также потребуется заголовок <unistd.h>. - person Jonathan Leffler; 19.07.2015
comment
@JonathanLeffler: Ну, иногда проще использовать старый добрый C;) - person nsilent22; 20.07.2015