如何把内存映射文件转换为FILE*

halod 2004-01-09 11:26:42
用mapviewoffile()创建的内存映射文件,如果我想用fwrite(),fread()
这种标准的C函数来操作,该怎么做?如果直接将(void*)转换为FILE*,则
fwrite()的返回值始终是0,到底该怎么做,请指教。
...全文
115 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
halod 2004-01-14
  • 打赏
  • 举报
回复
大概明白了,就是利用memcpy()重写Read()和Write()。
大家还有什么别的建议吗?
liotion 2004-01-14
  • 打赏
  • 举报
回复
同意自己寫一個,沒有其他的方法。
蒋晟 2004-01-13
  • 打赏
  • 举报
回复
自己写一个不难吧
这个是MFC的代码,抄来做示例。注意看Read和Write方法

// CStreamOnCString
// This is a helper class used by the CHtmlEditCtrlBase class to stream
// HTML into and out of the web browser control.
class CStreamOnCString : public IStream
{
public:
// Construction
CStreamOnCString()
{
m_current_index = 0;
}

CStreamOnCString(LPCTSTR szData):
m_strStream(szData)
{
m_current_index = 0;
}

// Copies the data currently held in this
// object into a CString
BOOL CopyData(CString& target)
{
target = m_strStream;
return TRUE;
}

// Sets the value of
BOOL SetData(LPCTSTR szData)
{
_ATLTRY
{
m_strStream = szData;
}
_ATLCATCHALL()
{
return FALSE;
}
return TRUE;
}

// Implementation
STDMETHOD(QueryInterface)(REFIID iid, void **ppUnk)
{
if (::InlineIsEqualGUID(iid, IID_IUnknown) ||
::InlineIsEqualGUID(iid, IID_IStream) ||
::InlineIsEqualGUID(iid, IID_ISequentialStream))
{
*ppUnk = (void*)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE AddRef( void)
{
return (ULONG)1;
}

ULONG STDMETHODCALLTYPE Release( void)
{
return (ULONG)1;
}

STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead)
{
if (pcbRead)
*pcbRead = 0;
if (m_strAnsi.GetLength() == 0)
m_strAnsi = m_strStream;

if (!pv)
return E_POINTER;

unsigned int length = m_strAnsi.GetLength();
char *pStream = m_strAnsi.GetBuffer();
if (!pStream)
return E_UNEXPECTED;

char *pStart = pStream + m_current_index;
char *pEnd = pStream + length;
if (pStart >= pEnd)
return S_FALSE; // no more data to read

int bytes_left = (int)(pEnd-pStart);
int bytes_to_copy = (int)min(bytes_left, (int)cb);
if (bytes_to_copy <= 0)
{
// reset members so this stream can be used again
m_current_index = 0;
m_strAnsi.Empty();
return S_FALSE;
}

memcpy(pv, pStream + m_current_index, bytes_to_copy);
if (pcbRead)
*pcbRead = (ULONG)bytes_to_copy;
m_current_index += bytes_to_copy;
m_strAnsi.ReleaseBuffer(0);
return S_OK;
}

STDMETHOD(Write)(const void *pv, ULONG cb, ULONG *pcbWritten)
{
if (pcbWritten)
*pcbWritten = 0;
try
{
#ifdef _UNICODE
int flags = IS_TEXT_UNICODE_UNICODE_MASK;
if (0 != IsTextUnicode((LPVOID)pv, cb, &flags))
{
// compiling UNICODE and got a UNICODE buffer
UINT nCharsToSkip = flags & IS_TEXT_UNICODE_SIGNATURE ? 1 : 0;
m_strStream.Append((wchar_t*)( ((wchar_t*)pv)+nCharsToSkip), (cb/sizeof(wchar_t))-nCharsToSkip);
if (pcbWritten)
*pcbWritten = cb-nCharsToSkip*sizeof(wchar_t);
}
else
{
// compiling UNICODE and got an ansi buffer
// convert ansi buffer to UNICODE buffer
CStringW strTemp((LPCSTR)pv, cb);
m_strStream.Append(strTemp);
if (pcbWritten)
*pcbWritten = cb;

}
#else
int flags = IS_TEXT_UNICODE_UNICODE_MASK;
if (0 != IsTextUnicode((LPVOID)pv, cb, &flags))
{
// compiling ANSI and got a UNICODE buffer
UINT nCharsToSkip = flags & IS_TEXT_UNICODE_SIGNATURE ? 1 : 0;
CStringA strTemp((const wchar_t*)pv + nCharsToSkip, (cb/sizeof(wchar_t))- nCharsToSkip);
m_strStream.Append(strTemp);
if (pcbWritten)
*pcbWritten = cb-nCharsToSkip*sizeof(wchar_t);
}
else
{
// compiling ANSI and got an ANSI buffer
m_strStream.Append((char*)pv, cb);
if (pcbWritten)
*pcbWritten = cb;
}
#endif
}
catch (CMemoryException* e)
{
e->Delete();
return E_OUTOFMEMORY;
}
return S_OK;
}

STDMETHOD(Seek)(LARGE_INTEGER , DWORD , ULARGE_INTEGER *)
{
return E_NOTIMPL;
}

STDMETHOD(SetSize)(ULARGE_INTEGER )
{
return E_NOTIMPL;
}

STDMETHOD(CopyTo)(IStream *, ULARGE_INTEGER , ULARGE_INTEGER *,
ULARGE_INTEGER *)
{
return E_NOTIMPL;
}

STDMETHOD(Commit)(DWORD )
{
return E_NOTIMPL;
}

STDMETHOD(Revert)( void)
{
return E_NOTIMPL;
}

STDMETHOD(LockRegion)(ULARGE_INTEGER , ULARGE_INTEGER , DWORD )
{
return E_NOTIMPL;
}

STDMETHOD(UnlockRegion)(ULARGE_INTEGER , ULARGE_INTEGER ,
DWORD )
{
return E_NOTIMPL;
}

STDMETHOD(Stat)(STATSTG *, DWORD )
{
return E_NOTIMPL;
}

STDMETHOD(Clone)(IStream **)
{
return E_NOTIMPL;
}

protected:
CString m_strStream;
CStringA m_strAnsi;
UINT m_current_index;

};
halod 2004-01-13
  • 打赏
  • 举报
回复
这样把PVOID转换成FILE*是不行的,在写入时会出错,即fwrite时会返回0
checkyvc6 2004-01-13
  • 打赏
  • 举报
回复
通过CreateMapFile和MapViewOfFile得到内存映射文件的指针,然后
FILE *m_pFile;
void *pData;
size_t len=::fwrite(pData,1,sizeof(int),m_pFile);
assert(len==sz);
halod 2004-01-13
  • 打赏
  • 举报
回复
拜托,我只是大概表示一下程序的流程,说一下实质的吧
liotion 2004-01-13
  • 打赏
  • 举报
回复
FILE *是个结构的指针,pData是内存的首地址,进行转换肯定不对。
liotion 2004-01-12
  • 打赏
  • 举报
回复
沒看過02年5月的雜誌,幫你頂。
halod 2004-01-12
  • 打赏
  • 举报
回复
还有人做过这方面的持久化工作吗?
linyudie 2004-01-12
  • 打赏
  • 举报
回复
写错了,我是想问为什么pData,m_pFile都不用赋值
linyudie 2004-01-12
  • 打赏
  • 举报
回复
FILE *m_pFile;
void *pData;
size_t len=::fwrite(pData,1,sizeof(int),m_pFile);
assert(len==sz);

还是没有看懂,pData还没有初始化呢啊?!直接用就可以?
halod 2004-01-11
  • 打赏
  • 举报
回复
我只是想利用fwrite()和fread()来读写文件,如果在内存中用指针来
操作,感觉比较麻烦。比如如果将一个int写入文件,我只需要
FILE *m_pFile;
void *pData;
size_t len=::fwrite(pData,1,sizeof(int),m_pFile);
assert(len==sz);
这样对每一个数据类型重载<<和>>,就可以持久化一个对象,具体例子在
程序员杂志02年5月。
如果用内存映射文件则怎么做?
bluebohe 2004-01-10
  • 打赏
  • 举报
回复
二者没啥联系,一个是内存,一个是文件指针
alphapiao 2004-01-10
  • 打赏
  • 举报
回复
LPVOID MapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
DWORD dwNumberOfBytesToMap );
返回是LPVOID啊,不是void
直接在内存操作不很好吗?何必用fwrite和fread
liotion 2004-01-10
  • 打赏
  • 举报
回复
内存映射文件是块内存,进行操作的时候是对内存进行操作不是对文件进行操作,一般都是用内存映射文件来实现进程之间的内存共享,fwirite()和fread()应该不行,没有试过。
checkyvc6 2004-01-09
  • 打赏
  • 举报
回复
我觉得用标准的HANDLE hFile不是更好吗?

或者用指针更方便

hHA
cnpeople 2004-01-09
  • 打赏
  • 举报
回复
没弄过,up
halod 2004-01-09
  • 打赏
  • 举报
回复
好像不行吧。首先,fwrite()和fread()只接受(FILE*)作为参数,其次,
mapviewoffile()返回是(void*)。我是要对内存映射文件操作,而不是对
文件进行操作。

2,643

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧