Случайные байты с фредом - PullRequest
0 голосов
/ 05 декабря 2009

# после

Имена моих переменных не важны! Этот код будет удален, когда он будет работать!

# * после 1005 * Хорошо, поэтому я использую fread в stdio.h для чтения текстового файла. Проблема в том, что я продолжаю чтение случайных байтов, которые не существуют в текстовом файле, насколько мне известно. Я предполагаю, что они являются частью схемы файлов, но я просто хочу убедиться, что это не мой код. #include "stdafx.h" #ifdef WIN32 #include <io.h> #else #include <sys/io.h> #endif #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include "n_script_timer.h" //using namespace std; #ifdef _INC_WCHAR typedef wchar_t CHR; #else typedef char CHR; #endif int _tmain(int argc, CHR* argv[]) { #ifndef _DEBUG if(argc == 1) { printf("You must drag a file onto this program to run it."); scanf("%*c"); return 0; } CHR* fname = argv[1]; #else #ifdef _INC_WCHAR const CHR fname[16] = L"f:\\deleteme.bin"; #else const CHR fname[16] = "f:\\deleteme.bin"; #endif #endif FILE* inFile; long len; struct Script_Timer a; //static const int bsize = 4096*6; static const int bsize = 84; typedef CHR chhh[bsize]; int alen; printf("#Opening File '%s' ...\n",fname); #ifdef _INC_WCHAR if((inFile = _wfopen(fname,L"rb")) == NULL) #else if((inFile = fopen(fname,"r")) == NULL) #endif { printf("Error opening file '%s' ",fname); return 0; } fseek(inFile,SEEK_SET,0); #ifdef _WIN32 len = _filelength( inFile->_file ); #else len = _filelength(inFile->_fileno); #endif printf(" !FileLength: %d\n",len); printf("#Creating Buffers...\n"); if(((float)len/(float)bsize) > (len/bsize)) { alen = (len/bsize) + 1; } else alen = (len/bsize); #ifdef WIN32 //chhh *cha = new chhh[alen]; chhh cha[alen]; #else chhh cha[alen]; #endif printf("#Reading File...\n"); Start_ST(&a); int i = 0; for(i=0;i<alen;++i) { fread(&cha[i],sizeof(CHR),bsize,inFile); printf("[%i]%s",i,cha[i]); } End_ST(&a); fclose(inFile); printf("Characters per millisecond: %f \n",((float)len/a.milliseconds)); printf("Characters per second: %f \n",((float)len/a.milliseconds) * 1000); scanf("%*c"); return 0; }

Ответы [ 5 ]

7 голосов
/ 05 декабря 2009

Пара странных вещей здесь:

int i = 0;
for(i=0;i<alen;++i)
{
   fread(&cha[i],sizeof(CHR),bsize,inFile);
   printf("[%i]%s",i,cha[i]);
}
  1. Нулевое завершение буфера перед его печатью (как указывало RageZ).

  2. Вы увеличиваете i при каждом повторении цикла, но каждый раз, когда вы читаете 84 символа (bsize) в &cha[i]. Я думаю, это должно означать, что вы видите только каждого 84-го персонажа.

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


EDIT: размер блока, который вы читаете, в порядке. Я запутался на минуту в typedef. Каждый раз, когда вы увеличиваете i на 1, он перемещает указатель на 84*sizeof(CHR), как вы и планировали. Тем не менее, вы не можете гарантировать, что он прочитал количество байтов, которое, по вашему мнению, было сделано. Если он оказался коротким, то у вас останется мусор в буфере: скажем, он прочитал 60 символов, что оставляет 24 мусорных символа перед точкой вставки для следующего чтения.

2 голосов
/ 05 декабря 2009

Обратите внимание, что ваш расчет alen будет неверным, если вы используете путь кода wchar_t, потому что bsize - это количество элементов в массиве, а не его размер в байтах.

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

2 голосов
/ 05 декабря 2009
typedef CHR chhh[bsize];

но

fread(&cha[i], sizeof(CHR), bsize, inFile);

В C ++ вам нужен дополнительный байт для '\ 0' в конце строки.

2 голосов
/ 05 декабря 2009

буфер cha должен быть заполнен null (0) раньше, иначе вы собираетесь получить немного мусора.

printf("[%i]%s",i,cha[i]);

Подобно тому, как printf выводит на экран до тех пор, пока не встретит NULL, так что в лучшем случае у вас будет какой-то мусор, наихудшее нарушение доступа, потому что вы обращаетесь к памяти, которой вы не владеете.

Примечание : Я советую вам дать значимое имя вашей переменной / typedef и т. Д., Как chhh, что не очень хорошо. Через несколько месяцев было бы больно даже изменять такой код!

0 голосов
/ 05 декабря 2009

У вас также могут быть ошибки переполнения буфера.

int i = 0;<br> for(i=0;i {<br> <blockquote><code> fread(&cha[i],sizeof(CHR),bsize,inFile);<br> printf("[%i]%s",i,cha[i]);<br></blockquote> }<br>

В приведенном выше цикле вы читаете количество bsize в каждой позиции в массиве cha. Если bsize не равен единице, у вас будут проблемы переполнения буфера, и данные в массиве не будут совпадать с данными в файле.

С Unicode я не думаю, что вы можете использовать бинарный ввод / вывод. Поскольку Unicode использует более одного байта для представления символов, вы сталкиваетесь с проблемами упорядочения байтов (Big Endian против Little Endian). Если ваша машинная архитектура имеет тот же Endianess, что и спецификация Unicode, у вас не возникнет проблем. Но если программа работает на другой архитектуре ...

Как уже говорили другие, не разрабатывайте специальный код для обработки переключения между Unicode и ASCII (8-битным). Посмотрите в руководстве по компилятору и используйте методы, которые будут работать на либо Unicode или ASCII, в зависимости от переключателя компилятора. Пишите новый код только тогда, когда компилятор или ОС не имеют нужной вам функциональности. В этом случае вам нужен фред , который будет работать на любом из них; но точно не фред .

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