Win Api 高速磁盘读写封装

#pragma once

#include <string>
#include <memory>


class WinFile
{
public:
	WinFile(const std::string& path = "");
	WinFile(WinFile&& file);
	~WinFile();

	void open(std::string path);
	operator bool() const;

	WinFile& read(char* data, size_t size);
	WinFile& write(char* data, size_t size);
	size_t gcount() const;

	WinFile& seekg(size_t pos);
	WinFile& seekp(size_t pos);
	bool eof() const;

private:
	class Private;
	std::unique_ptr<Private> d;
};

 

#include "win_file.h"
#include <Windows.h>
#include <vector>


class WinFile::Private
{
public:
	Private(std::string path)
	{
		m_hFile = nullptr;
		m_offset = 0;
		m_gcount = 0;
		m_size = 0;
		m_complete = true;
		m_pageSize = 512;

		if (path != "") {
			m_hFile = CreateFileA(path.c_str(),
				GENERIC_READ | GENERIC_WRITE,
				FILE_SHARE_READ | FILE_SHARE_WRITE,
				NULL,
				OPEN_ALWAYS,
				FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
				NULL);

			if (m_hFile) {
				LARGE_INTEGER size;
				if (GetFileSizeEx(m_hFile, &size))
					m_size = size.QuadPart;
			}
		}
	}

	~Private()
	{
		if (m_hFile)
			CloseHandle(m_hFile);
	}

	size_t read(char *data, size_t offset, size_t size)
	{
		auto event = CreateEvent(NULL, TRUE, FALSE, NULL);
		OVERLAPPED overlap = OVERLAPPED();
		overlap.Offset = offset & ((1LL << 32) - 1);
		overlap.OffsetHigh = offset >> 32;
		overlap.hEvent = event;
		DWORD readSize = 0;

		BOOL rc = ReadFile(m_hFile, data, size, &readSize, &overlap);
		if (rc) {
			// done
		}
		else if (GetLastError() == ERROR_IO_PENDING) {
			WaitForSingleObject(&event, INFINITE);
			bool rc = GetOverlappedResult(m_hFile, &overlap, &readSize, FALSE);
			if (!rc && GetLastError() == ERROR_IO_INCOMPLETE) {
				bool rc = GetOverlappedResult(m_hFile, &overlap, &readSize, TRUE);
			}
		}
		else {
			// failed
		}
		return readSize;
	}

	size_t write(char *data, size_t offset, size_t size)
	{
		auto event = CreateEvent(NULL, TRUE, FALSE, NULL);
		OVERLAPPED overlap = OVERLAPPED();
		overlap.Offset = offset & ((1LL << 32) - 1);
		overlap.OffsetHigh = offset >> 32;
		overlap.hEvent = event;
		DWORD written = 0;

		BOOL rc = WriteFile(m_hFile, data, size, &written, &overlap);
		if (rc) {
			// done
		}
		else if (GetLastError() == ERROR_IO_PENDING) {
			WaitForSingleObject(&event, INFINITE);
			bool rc = GetOverlappedResult(m_hFile, &overlap, &written, FALSE);
			if (!rc && GetLastError() == ERROR_IO_INCOMPLETE) {
				bool rc = GetOverlappedResult(m_hFile, &overlap, &written, TRUE);
			}
		}
		else {
			// failed
		}
		return written;
	}

	HANDLE m_hFile;
	size_t m_offset;
	size_t m_gcount;
	size_t m_size;
	size_t m_pageSize;
	bool m_complete;
	std::vector<char> m_buf;
};


WinFile::WinFile(const std::string& path)
{
	d = std::make_unique<Private>(path);
}

WinFile::WinFile(WinFile && file)
{
	d = std::move(file.d);
}


WinFile::~WinFile()
{
}

void WinFile::open(std::string path)
{
	d = std::make_unique<Private>(path);
}

WinFile::operator bool() const
{
	if (d->m_hFile == INVALID_HANDLE_VALUE)
		return false;
	return d->m_complete;
}

WinFile & WinFile::read(char * data, size_t size)
{
	size_t buffedSize = d->m_buf.size();
	if (buffedSize > 0 || size < d->m_pageSize || (size & (size - 1) != 0)) {
		if (buffedSize < size) {
			size_t npage = round(1. * (size - buffedSize) / d->m_pageSize);
			size_t pagesSize = npage * d->m_pageSize;
			d->m_buf.resize(buffedSize + pagesSize);
			char *buf = d->m_buf.data() + buffedSize;

			size_t readSize = d->read(buf, d->m_offset, pagesSize);
			if (readSize < pagesSize)
				d->m_buf.resize(buffedSize + readSize);
			d->m_offset += readSize;
			buffedSize = d->m_buf.size();
		}

		size_t copySize = min(size, buffedSize);
		if (copySize > 0) {
			memcpy(data, d->m_buf.data(), copySize);
			size_t leftSize = buffedSize - copySize;
			if (leftSize > 0)
				memcpy(d->m_buf.data(), d->m_buf.data() + copySize, leftSize);
			d->m_buf.resize(leftSize);
		}
		d->m_gcount = copySize;
		d->m_complete = size == copySize;
	}
	else {
		size_t readSize = d->read(data, d->m_offset, size);
		d->m_gcount = readSize;
		d->m_complete = size == readSize;
		d->m_offset += readSize;
	}
	return *this;
}

WinFile & WinFile::write(char * data, size_t size)
{
	size_t written = d->write(data, d->m_offset, size);
	d->m_gcount = written;
	d->m_complete = size == written;
	d->m_offset += written;
	return *this;
}

size_t WinFile::gcount() const
{
	return d->m_gcount;
}

WinFile & WinFile::seekg(size_t pos)
{
	d->m_offset = pos;
	return *this;
}

WinFile & WinFile::seekp(size_t pos)
{
	d->m_offset = pos;
	return *this;
}

bool WinFile::eof() const
{
	return d->m_offset >= d->m_size;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值