ReadFile Win32 API - PullRequest
       2

ReadFile Win32 API

2 голосов
/ 25 октября 2010

я хочу прочитать файл ... но ... когда я отлаживаю свою программу, она запускается, но появляется всплывающее окно с сообщением о том, что системное программирование перестало работать, и в консоли написано, что нажмите Enter, чтобы закрыть программу.мой код ::

// System Programming.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "iostream"
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE hin;
    HANDLE hout;
    TCHAR buff[20]= {'q','2','3'};
    TCHAR buff2[20]={'a','v'};
    hin = CreateFile(_T("Abid.txt"),GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
    if(hin == INVALID_HANDLE_VALUE)
    {
        cout<<"error";
    }

    WriteFile(hin,buff,40,0,NULL);
    CloseHandle(hin);

    hout = CreateFile(_T("Abid.txt"),GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

    if(hout == INVALID_HANDLE_VALUE)
    {
        cout<<"error";
    }

    ReadFile(hout,buff2,40,0,NULL);
    CloseHandle(hout);
    return 0;
}

Ответы [ 4 ]

12 голосов
/ 25 октября 2010

Согласно MSDN, параметр lpNumberOfBytesWritten может иметь значение NULL, только если параметр lpOverlapped не равен NULL.Таким образом, вызовы должны быть

DWORD nWritten;
WriteFile(hin, buff, 40, &nWritten, NULL);

и

DWORD nRead;
ReadFile(hout, buff2, 40, &nRead, NULL);

Также переименуйте hin и hout .

5 голосов
/ 25 октября 2010

Другие уже ответили на ваш вопрос. Это о коде.

// Your code:
// System Programming.cpp : Defines the entry point for the console application.
//

Просто удалите этот комментарий. Это не правда :-) Точка входа для вашей программы - это место, где машинный код начинает выполняться, а с помощью цепочки инструментов Microsoft это определяется параметром компоновщика /entry.

Обратите внимание, что документация Microsoft, как правило, смущает точки входа, например, он всегда, так или иначе, документировал неверную подпись для точки входа.

Это одна из самых печально известных ошибок документации Microsoft, и, учитывая, что она сохраняется в различных формах в течение 15 лет, я думаю, что это что-то говорит (хотя точно не знаю, что именно).

// Your code:
#include "stdafx.h"

Вам не нужен этот автоматически сгенерированный заголовок. Вместо этого используйте <windows.h>. Минимальный способ включить <windows.h> для вашей программы:

#undef  UNICODE
#define UNICODE
#include <windows.h>

Для C ++ в целом вы также должны убедиться, что STRICT и NOMINMAX определены перед включением <windows.h>. С современными инструментами, по крайней мере, STRICT определяется по умолчанию, но это не помешает. Без этого некоторые объявления не будут компилироваться с помощью компилятора C ++, по крайней мере, без переинтерпретации приведений, например диалоговые процедуры.

// Your code:
#include "iostream"
using namespace std;

Почти нормально.

Сделайте это:

#include <iostream>
using namespace std;

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

// Your code:
int _tmain(int argc, _TCHAR* argv[])

О нет! Не делай этого. Это «особенность» Microsoft, которая помогает поддерживать Windows 9.x. И это актуально только в том случае, если вы используете динамическую связь MFC и нацелены на Windows 9.x; без MFC на картинке вы бы просто использовали слой Microsoft Unicode.

На какую область вы ориентируетесь на Windows 9.x с приложением, использующим динамически связанную MFC?

Вместо этого делайте ...

int main()

... который является стандартным, или используйте расширение языка Microsoft ...

int wMain( int argc, wchar_t* argv[] )

... если вы хотите обрабатывать аргументы командной строки «простым» способом.

// Your code:
{
    HANDLE hin;
    HANDLE hout;
    TCHAR buff[20]= {'q','2','3'};
    TCHAR buff2[20]={'a','v'};

Материал TCHAR - это нечто большее, чем поддержка MFC в Windows 9.x.

Помимо того, что это совершенно не нужно (по-видимому, вы на самом деле не ориентируетесь на Windows 9.x, не так ли?), Оно скрывает ваши намерения и ранит глаза.

Вы имели в виду ...

char buff[20] = {'q', '2', '3'};

... возможно?

// Your code:
    hin = CreateFile(_T("Abid.txt"),GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
    if(hin == INVALID_HANDLE_VALUE)
    {
        cout<<"error";
    }

Как уже упоминалось, OPEN_EXISTING не логично, когда вы создаете файл, и аргумент указателя счетчика не может быть 0 для вашего использования.

При использовании <windows.h> с определением UNICODE, как и должно быть, аргумент имени файла должен быть указан как L"Abid.txt".

Приветствия и hth.,

1 голос
/ 25 октября 2010

Проблема в том, что вы передаете NULL-указатель для параметра lpNumberOfBytesWritten / lpNumberOfBytesread. Хотя это необязательный параметр, есть условие:

Этот параметр может иметь значение NULL, только если параметр lpOverlapped не равен NULL

Кроме того, размер ваших буферов может быть неправильным:

WriteFile(hin,buff,40,0,NULL);  // says that buff has 40 bytes

ReadFile(hout,buff2,40,0,NULL); // says that buff2 has 40 bytes

Но если вы компилируете для ANSI вместо UNICODE, они будут иметь размер только 20 байт.

Возможно, вам следует использовать sizeof(buff) и sizeof(buff2).

0 голосов
/ 25 октября 2010

Если исходный код пытается создать файл как новый файл, тогда вы не можете использовать OPEN_EXISTING, вам нужно использовать OPEN_ALWAYS (или какой-либо другой вариант создания) для этого вызова.

Использование OPEN_EXISTING для чтения будет в порядке.

кстати, как только это будет исправлено, вызовы WriteFile вызывают нарушение доступа, так как вы пытаетесь записать больше байтов, содержащихся в вашем массиве.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...