2010-10-24 2 views
2

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

// 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; 
} 
+0

Что здесь проблема? Пробовали ли вы установить точку останова на или внутри _tmain и пройти через код? –

+0

Попробуйте использовать GetLastError после каждой функции. – Abyx

+0

Кстати, это должно быть '', а не '' iostream''. –

ответ

11

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

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

и

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

Кроме того, переименовывать гин и Hout.

0

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

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

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

+0

так что я делаю? Создавать новое? –

+0

@Abid, это сработает - проверьте документы здесь: http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx –

1

Проблема в том, что вы передаете указатель 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).

5

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

// 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".

Приветствия & НТН.,

+1

Пока я согласен с настроением ваших пунктов: 1. «stdafx.h» необходимо с настройками проекта по умолчанию (предварительно скомпилированных заголовков), и компилятор будет паниковать, если он не сможет его найти. 2. char buff [20] = ['q', '2', '3']; ??? Когда [] были законными в списке инициализаторов? Это {}. –

+1

@ Крис: относительно ваших точек (предположительно) об использовании IDE Visual Studio нет, «stdafx.h» даже не требуется в Visual Studio. Это просто по умолчанию для определенных видов проектов Visual Studio. Просто отключите предварительно скомпилированные заголовки в настройках проекта. Кроме того, нет такой вещи, как компилятор в панике. Что касается опечатки, спасибо. –

+1

@Chris: также имя не обязательно должно быть «stdafx.h», вы можете указать любой файл, который вы хотите, в параметрах командной строки/проекта. – Skizz

Смежные вопросы