使用内存映射文件时删除空字节

时间:2013-11-26 07:08:06

标签: c# null byte

我使用4个线程将数据写入文件。每个线程使用MMF来写入文件的一部分。 当我用Notpad ++打开文件时,它总是在文件的一部分之间显示空字节。

线程1写1 线程2写入12 线程3写入123 线程4写入1234

结果如下: 1Nul12Nul123Nul1234Nul

MMF需要2个字节来写“1”字符,但实际上“1”字符只有一个字节。

如果我将1个字节设置为MMF,它将抛出:访问者中没有足够的字节来写入此位置。

如何删除这些空字节?

更新代码: 我只使用2个线程以便于查看。

    static void Main(string[] args)
    {
        File.Delete(@"C:\abc.txt");

        CancellationTokenSource tokenSource = new CancellationTokenSource();
        CancellationToken cancellationToken = tokenSource.Token;

        // Write data to file using MMF.
        Task<int>[] tasks = new Task<int>[2];
        tasks[0] = new Task<int>(() => F1(0, 2, "1", cancellationToken), cancellationToken);
        tasks[1] = new Task<int>(() => F2(2,4, "12", cancellationToken), cancellationToken);

        // Create MMF File.
        MemoryMappedFileSecurity CustomSecurity = new MemoryMappedFileSecurity();

        MemoryMappedFile MemoryMapped = MemoryMappedFile.CreateFromFile(

               new FileStream(@"C:\abc.txt", FileMode.OpenOrCreate),
               "MapAbcFile",// Name

               20,                                    // Size

               MemoryMappedFileAccess.ReadWrite,               // Access type

               null,                          // You can customize the security

               HandleInheritability.None
               , false);              // Inherit to child process   



        try
        {
            ParallelOptions op = new ParallelOptions();
            op.CancellationToken = tokenSource.Token;
            Parallel.ForEach(tasks, op, t =>
            {
                try
                {
                    t.Start();
                }
                catch (Exception)
                {

                    tokenSource.Cancel();
                }

            });

            // Wait for all the tasks to finish.
            Task.WaitAll(tasks, cancellationToken);

            Console.WriteLine("Done!");
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Cancelled!");
        }
        catch (AggregateException ae)
        {
            //tokenSource.Cancel();

            Console.WriteLine("AggregateException!");
            // Assume we know what's going on with this particular exception.
            // Rethrow anything else. AggregateException.Handle provides
            // another way to express this. See later example.
            foreach (var ie in ae.InnerExceptions)
            {
                Console.WriteLine(ie.Message);
            }
        }

        MemoryMapped.Dispose();

    }

    private static int F1(long offset, long size, string firstName, CancellationToken cancellationToken)
    {
        Console.WriteLine(string.Format("ManagedThreadId(F1): {0} - {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToLongTimeString()));
        MemoryMappedFile MemoryMapped = MemoryMappedFile.OpenExisting("MapAbcFile");
        MemoryMappedViewAccessor WriteFirstPart = MemoryMapped.CreateViewAccessor(offset, size, MemoryMappedFileAccess.ReadWrite);
        int i = 0;

        foreach (char item in firstName.ToCharArray())
        {
            WriteFirstPart.Write(i, item);
            i++;
        }

        WriteFirstPart.Dispose();
        return 1;
    }
    private static int F2(long offset, long size, string lastName, CancellationToken cancellationToken)
    {
        Console.WriteLine(string.Format("ManagedThreadId(F2): {0} - {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToLongTimeString()));

        MemoryMappedFile MemoryMapped = MemoryMappedFile.OpenExisting("MapAbcFile");
        MemoryMappedViewAccessor WriteFirstPart = MemoryMapped.CreateViewAccessor(offset, size, MemoryMappedFileAccess.ReadWrite);
        int i = 0;
        foreach (char item in lastName.ToCharArray())
        {
            WriteFirstPart.Write(i, item);
            i++;
        }
        WriteFirstPart.Dispose();

        return 1;
    }

1 个答案:

答案 0 :(得分:2)

你的错误在这里:

  

但实际上“1”字符只有一个字节。

然而,Char实际上定义为:

  

将字符表示为UTF-16代码单元。

UTF-16代码单元占用两个字节。

如果您希望1只占用一个字节,那么您需要使用System.Text.Encoding类中的某些东西来使用说ASCII或UTF-8,或者使用其他编码来处理字符{ {1}}占用一个字节。 E.g。

1