using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace Mem1
{
class Program
{
static void Main(string[] args)
{
Mem m = new Mem();
string text = File.ReadAllText(@"aa.txt", Encoding.Default);
m.Write(text);
string st = m.Read();
//finally
m.Close();
}
}
class Mem
{
//full defination
[Flags]
public enum FileMapAccess : uint
{
FileMapCopy = 0x0001,
FileMapWrite = 0x0002,
FileMapRead = 0x0004,
FileMapAllAccess = 0x001F,
fileMapExecute = 0x0020,
}
[Flags]
enum FileMapProtection : uint
{
PageReadonly = 0x02,
PageReadWrite = 0x04,
PageWriteCopy = 0x08,
PageExecuteRead = 0x20,
PageExecuteReadWrite = 0x40,
SectionCommit = 0x8000000,
SectionImage = 0x1000000,
SectionNoCache = 0x10000000,
SectionReserve = 0x4000000,
}
const int INVALID_HANDLE_VALUE = -1;
private Semaphore m_Write; //可写的信号
private Semaphore m_Read; //可读的信号
private IntPtr handle; //文件句柄
private IntPtr addr; //共享内存地址
private const uint mapLength = 10240; //共享内存长,如果要是超长的话,应另外处理,最好是分配足够的内存
[DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]
private static extern IntPtr CreateFileMapping(
IntPtr hFile,
UInt32 lpAttributes,
FileMapProtection flProtect,
UInt32 dwMaximumSizeHigh,
UInt32 dwMaximumSizeLow,
string lpName);
[DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")]
private static extern IntPtr OpenFileMapping(
UInt32 dwDesiredAccess,
int bInheritHandle,
string lpName);
[DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")]
private static extern IntPtr MapViewOfFile(
IntPtr hFileMappingObject,
FileMapAccess dwDesiredAccess,
UInt32 dwFileOffsetHight,
UInt32 dwFileOffsetLow,
UInt32 dwNumberOfBytesToMap);
[DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile")]
private static extern int UnmapViewOfFile(IntPtr lpBaseAddress);
[DllImport("Kernel32.dll", EntryPoint = "CloseHandle")]
private static extern int CloseHandle(IntPtr hObject);
public void Write(string text)
{
Console.WriteLine("write");
m_Write = new Semaphore(1, 1, "WriteMap");
m_Read = new Semaphore(0, 1, "ReadMap");
IntPtr hFile = new IntPtr(INVALID_HANDLE_VALUE);
handle = CreateFileMapping(hFile, 0, FileMapProtection.PageReadWrite, 0, mapLength, "shareMemory");
addr = MapViewOfFile(handle, FileMapAccess.FileMapAllAccess, 0, 0, 0);
m_Write.WaitOne();
byte[] sendStr = Encoding.Unicode.GetBytes(text + '/0');
if (sendStr.Length < mapLength) //4G max limit on FAT32 ?
StrCopy(sendStr, addr);
else throw new AccessViolationException("...");
m_Read.Release();
}
public string Read()
{
Console.WriteLine("read");
m_Write = Semaphore.OpenExisting("WriteMap");
m_Read = Semaphore.OpenExisting("ReadMap");
handle = OpenFileMapping(0x0002, 0, "shareMemory");
m_Read.WaitOne();
IntPtr str = MapViewOfFile(handle, FileMapAccess.FileMapAllAccess, 0, 0, 0);
string s = Pop(str);
m_Write.Release();
return s;
}
static unsafe string Pop(IntPtr src)
{
byte[] byteDst = new byte[mapLength];
fixed (byte* pSrc = byteDst)
{
byte* pSrc1 = (byte*)src;
byte* pDest1 = pSrc;
for (int i = 0; i < byteDst.Length; i++)
{
*pDest1 = *pSrc1;
pSrc1++;
pDest1++;
}
}
UnicodeEncoding encoding = new UnicodeEncoding();
string constructedstring = encoding.GetString(byteDst);
return constructedstring;
}
static unsafe void StrCopy(byte[] byteSrc, IntPtr dst)
{
fixed (byte* pSrc = byteSrc)
{
byte* pDst = (byte*)dst;
byte* psrc = pSrc;
for (int i = 0; i < byteSrc.Length; i++)
{
*pDst = *psrc;
pDst++;
psrc++;
}
}
}
public void Close()
{
UnmapViewOfFile(addr);
CloseHandle(handle);
}
}
}
去掉原文(找不到从哪里看的了,可以G到很多相似结果)一些注释。 代码改了一下, 用了pinvoke的定义, 全部代码win7下测试可用。
大概核心意思就是放到内存里读。 C#里没有strcpy, 需要用fixed关键字来处理一下。
然后字符写入读出的编码一致就可以支持中文了。
另外一定要释放资源, 否则会变得很慢。