Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.11.2009, 01:11   #1
nazavrik
Форумчанин
 
Аватар для nazavrik
 
Регистрация: 01.09.2008
Сообщений: 178
По умолчанию ReadFile

Доброе время суток!

Считываю данные из файла:

Код:
size_t MyClass::RecvFrom(_TCHAR *buf, DWORD bufLen)
{
	HANDLE hFile = CreateFile(pBufData, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	if(hFile == INVALID_HANDLE_VALUE)
	{
		_tprintf(_TEXT("File can not open\n"));
		return(-1);
	}
	
	DWORD nBytesRead;
	
	bool bFlag = ReadFile(hFile, buf, bufLen, &nBytesRead, NULL);

	if(bFlag)
	{
		_tprintf(_TEXT("File not read\n"));
		return(-1);
	}

	_tprintf(_TEXT("Buf - %s\n"), buf); //!!

	CloseHandle(hFile);
	return(0);
}
На экран выводятся квадратики непонятные, что не соответствует содержимому файла. В чем может быть дело?
Быть радикальным - значит понять вещь в её корне. К.Маркс
nazavrik вне форума Ответить с цитированием
Старый 21.11.2009, 10:17   #2
ROD
Linux C++ Qt ARM
Старожил
 
Аватар для ROD
 
Регистрация: 30.11.2008
Сообщений: 3,030
По умолчанию

В кодировке файла не верной причина быть может.
Дилетант широкого профиля.

"Слова ничего не стоят - покажите мне код!" © Линус Торвальдс
ROD вне форума Ответить с цитированием
Старый 21.11.2009, 21:54   #3
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Меня смущает обилие макросов (_TCHAR, _tprintf, _TEXT) для переносимости кода между юникод/не юникод проектами. В свойствах проекта юникод включен? Файл юникодный или в какой-нибудь 1251 кодировке?
pu4koff вне форума Ответить с цитированием
Старый 22.11.2009, 01:27   #4
lennon
Заблокирован
 
Регистрация: 18.11.2007
Сообщений: 254
По умолчанию

Код:
size_t MyClass::RecvFrom(_TCHAR *buf, DWORD bufLen)
{
	HANDLE hFile = CreateFile(pBufData, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	if(hFile == INVALID_HANDLE_VALUE)
	{
		_tprintf(_TEXT("File can not open\n"));
		return(-1);
	}
	
	DWORD nBytesRead;
	
	bool bFlag = ReadFile(hFile, buf, bufLen, &nBytesRead, NULL);

	if(bFlag)
	{
		_tprintf(_TEXT("File not read\n"));
		return(-1);
	}

	printf("Buf - %s\n"), buf); //!!

	CloseHandle(hFile);
	return(0);
}
lennon вне форума Ответить с цитированием
Старый 22.11.2009, 11:22   #5
nazavrik
Форумчанин
 
Аватар для nazavrik
 
Регистрация: 01.09.2008
Сообщений: 178
По умолчанию

Спасибо! Действительно все дело было в выводе.

Сейчас встала другая проблема

Оказывается оператор new выделяет памяти больше, чем запрашивается (лишняя память, как я понял, необходима для хранения размера выделенной памяти, в которой нуждается оператор delete []). В связи с этим процесс выделения памяти для буфера определенного размера, записи в этот буфер такого же размера информации и последующий вывод буфера на печать приводит к выводу в конце лишних каракуль
Быть радикальным - значит понять вещь в её корне. К.Маркс
nazavrik вне форума Ответить с цитированием
Старый 22.11.2009, 13:04   #6
lennon
Заблокирован
 
Регистрация: 18.11.2007
Сообщений: 254
По умолчанию

=================================
предыдущая ошибка заключалась в следующем:
_tprintf выводит строки unicode, тоесть wchar_t строки, а у вас в файле данные находились в обычной кодировке ansi
=================================

Следующий ваш вопрос:

под буфером я так понял вы подразумеваете строку. Выделите на один байт больше и в этот последний байт поместите NULL - ноль байт.
Код:
 char [] test = "test";
 int len = strlen(test);
 char * str = new char[len+1];
 str[len+1] = 0; //или memset(str,0,len+1);
 strcpy(str,test);

 printf("%s",str);
неоднократно повторяю.... проблема в том, что строки в с++ должны заканчивать нулевым байтом, для того чтобы можно было определить какова их длина (пример strlen) и где они заканчиваються. Вот другой пример (собственно я так делаю всегда)

Код:
  char [] test = "test";
  char * str = (char*)calloc(strlen(test)+1,sizeof(char)); //здесь +1 - место для нулевого байта который свидетельствует о конце строки, так же эта функция сама заполняет весь массив NULL'ами
  strcpy(str,test);

 printf("%s",str);
пример функции strlen
Код:
int strlen(const char * str)
{
 int i = 0;
 while (str[i] != 0 /*NULL*/) i++;
 return i;
}

Последний раз редактировалось lennon; 22.11.2009 в 13:12.
lennon вне форума Ответить с цитированием
Старый 22.11.2009, 13:46   #7
nazavrik
Форумчанин
 
Аватар для nazavrik
 
Регистрация: 01.09.2008
Сообщений: 178
По умолчанию

Проблема в следующем. Я использую оператор new:

Код:
	char *buf = new char[a];
	int i = strlen(buf);
количество выделяемой памяти определяется параметром a, так?

Если а = 1,2,3,4, то i принимает значение 16.
Если а = (5-12), то i принимает значение 24.
Если а = (13-20), то i принимает значение 32.
Если а = (21-28), то i принимает значение 40.

и т.д. Т.е. размер буфера всегда на 12 больше фактически запрашиваемого размера памяти. VS2008
Быть радикальным - значит понять вещь в её корне. К.Маркс
nazavrik вне форума Ответить с цитированием
Старый 22.11.2009, 13:59   #8
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Просто с мусором тебе так везёт. После выделения памяти, нужно обнулять данные, прежде, чем использовать их. К размеру выделяемого блока приведённый код вообще не имеет никакого отношения. Напиши так:
Код:
	char *buf = new char[a];
	buf[0] = '\0';
	int i = strlen(buf);
Теперь i всегда будет равна нулю. Значит компилятор вообще память выделять не стал чтоль?
pu4koff вне форума Ответить с цитированием
Старый 22.11.2009, 14:33   #9
nazavrik
Форумчанин
 
Аватар для nazavrik
 
Регистрация: 01.09.2008
Сообщений: 178
По умолчанию

Ок. Задача стоит так. Из файла прочесть заданное количество байтов- bufLen. Я уже приводил код ранее, повторюсь:

Код:

HANDLE hFile = CreateFile(pBufData, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);

	if(hFile == INVALID_HANDLE_VALUE)
	{
		_tprintf(_TEXT("File can not open"));
		return(-1);
	}

	DWORD bRead;

	char *buff = new char[bufLen];

	bool bResult = ReadFile(hFile, buff, bufLen, &bRead, NULL);

	printf("buf - %s", buff); 

	CloseHandle(hFile);
Результат - всегда один - на экран выводится 40 символов, не зависимо от значения bufLen. Что конкретно не так7

Если бы задача ограничивалась выводом считанных байтов, то все было бы просто:

Код:
	int i=0;

	while(bRead!= 0)
	{
		std::cout<<buff[i];
		bRead--;
                i++;
	}
Но мне нужно оперировать ими. А для этого нужно их корректное представление в буфере.
Быть радикальным - значит понять вещь в её корне. К.Маркс

Последний раз редактировалось nazavrik; 22.11.2009 в 14:45.
nazavrik вне форума Ответить с цитированием
Старый 22.11.2009, 14:39   #10
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Файл текстовый или с бинарными данными? В bRead 40 записано и на экран 40 символов выводится?
pu4koff вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц