Sign in to follow this  

fread fails...

This topic is 2850 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello! I've made a package system for my engine, which creates "File-Chunks", everytime the user imports a file. This way, the Files can be easily deleted/Renamed/Moved/etc. That works fine until the point I want to save them all to a file and to load it again. Saving (with fwrite) seems to work, but loading (with fread) does not! Well, it does, but just for small portions of Data. When I want to load 4 bytes for example, it works, but when I want to read 1mb, it says, that I am at EOF. I checked already, if it wants to load too much, but the saved size is identical with the loaded size. Here is the code:
void WPckFileChunk::SaveToFile(FILE* File)
{
	WCHAR Msg[256];

	wsprintf(LPS Msg,L"Saving Chunk: \"%s\", Size: %d",LPS FileName,Size);
	InfoBox(LPS Msg);

	fwrite(LPS FileName,sizeof(WCHAR)*MAX_PATH,1,File);
	fwrite(&FolderID,sizeof(UINT),1,File);
	fwrite(&bFolder,sizeof(bool),1,File);
	fwrite(&Size,sizeof(UINT),1,File);
	int Written=fwrite(Data,Size,1,File);

	if(Written<=0)
	{
		ErrorBox(L"Failed to write Chunk Data!");
	}

	WCHAR huhu[20];
	wcscpy(LPS huhu,L"Hello!!!");
	fwrite(LPS huhu,sizeof(WCHAR)*20,1,File);
	
	fwrite(&ID,sizeof(UINT),1,File);
}

void WPckFileChunk::LoadFromFile(FILE* File)
{
	fread(LPS FileName,sizeof(WCHAR)*MAX_PATH,1,File);
	fread(&FolderID,sizeof(UINT),1,File);
	fread(&bFolder,sizeof(bool),1,File);
	fread(&Size,sizeof(UINT),1,File);

	WCHAR Msg[256];

	wsprintf(LPS Msg,L"Loading Chunk-Data: \"%s\", Size: %d",LPS FileName,Size);
	InfoBox(LPS Msg);


	Data = new byte[Size];
	int Read=fread(Data,Size,1,File);

	DWORD Err=GetLastError();

	if(Read<=0)
	{
		if(feof(File))
		{
			ErrorBox(L"Reached the end-of-file while loading the Chunk-Data!");
		}else
		{
			ErrorBox(L"Error reading Chunk-Data!");
		}

	}

	WCHAR huhu[20];
	fread(LPS huhu,sizeof(WCHAR)*20,1,File);

	fread(&ID,sizeof(UINT),1,File);
}

I check with the writing of "Hello!", if I am at the right position. Its just debugging. Any suggestions?

Share this post


Link to post
Share on other sites
What is LPS? If it's a type name, your code should not compile (you don't specify the types of parameters when you call a function, only when you declare or implement it), so I can only assume it's some sort of strange macro.

Other than that, did you make sure to open the file in binary mode, both when loading and when saving?

Share this post


Link to post
Share on other sites
Does your info box give the correct size information? Also, what is the value of Err when your problem occurs?

Also, it may make no difference, but, to use the returned value from fread/fwrite correctly (a size_t = number of items read/written), you should have:

UINT Read = fread(Data,Size,1,File);
if( Read != 1 )
{
if(Size==0) { ..message that Size was zero.. }
else if( ... )

Also, is file opened in binary mode? EDIT: as Zahlman says.

Share this post


Link to post
Share on other sites
LPS is a macro to use WCHARs as a pointer:

#define LPS (LPWSTR)&


Just a handy tool :)

Awww! I wanted to copy the opening-code, and I noticed, that it isn't opened in
"rb" mode! I forget this everytime! :(

Thanks!

Share this post


Link to post
Share on other sites
That define looks dangerous. Casting pointers is something you should be very careful with.

Other than that, I would probably write your code something like this:

struct Header {
// I would probably use a variable length string, but this simplifies
WCHAR FileName[MAX_PATH];
UINT FolderID;
bool IsFolder;
UINT Size;
};

template<class PODType>
std::ostream &write(std::ostream &out, const PODType &instance)
{
const char *pointer = reinterpret_cast<const char *>(&instance);
out.write(pointer, sizeof(instance));
}

template<>
std::ostream &write(std::ostream &out, const std::wstring &string)
{
if(write(out, string.size())
{
const char *pointer = reinterpret_cast<const char *>(string.c_str());
out.write(pointer, string.size() * sizeof(std::wstring::value_type));
}

return out;
}

void WPckFileChunk::SaveToStream(std::ostream &out) const
{
std::wstringstream Msg;
Msg << L"Saving Chunk: \"" << Header.FileName << "\", Size: " << Header.Size;
InfoBox(Msg.str().c_str());

// Data is of type std::vector<char>
boolean success = write(out, Header) && out.write(&Data.front(), Data.size());

if(! success )
{
ErrorBox(L"Failed to write Chunk Data!");
}

std::wstring huhu = L"Hello!!!";


success = write(out, huhu) && write(out, ID);

// Error handling?
}

template<class PODType>
std::istream &read(std::istream &in, PODType &instance)
{
char *pointer = reinterpret_cast<char *>(&instance);
in.read(pointer, sizeof(instance));
return in;
}

template<>
std::istream &read(std::istream &in, std::wstring &string)
{
typedef std::wstring::value_type char_type;
typedef char_type *ptr;

std::wstring::size_type size;
if(read(out, size)
{
std::vector<char> data(size * sizeof(char_type));
in.read(&data.front(), data.size());

ptr begin = reinterpret_cast<ptr>(&data.front());
ptr end = begin + size;
string.assign(begin, end);
}
return in;
}

void WPckFileChunk::LoadFromStream(std::istream &in)
{
bool success = read(in, Header);

if(! success )
{
// Error handling
}

std::wstringstream Msg;
Msg << L"Loading Chunk-Data: \"" << Header.FileName << "\", Size: " << Header.Size;
InfoBox(Msg.str().c_str());

Data.resize(Header.Size);

if(! in.read(&Data.front(), Data.size())
{
ErrorBox(L"Reached the end-of-file while loading the Chunk-Data!");
}

std::wstring huhu;
success = read(in, huhu) && read(in, ID);

// Error handling
}


Something like that, I haven't compiled or tested it or anything. The main point is removing lots of opportunity for error by using template functions to detect the types (and hence sizeof()) being used automatically. That and adding more error checking so that any errors are detected.

Share this post


Link to post
Share on other sites

This topic is 2850 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this