65.9K
CodeProject 正在变化。 阅读更多。
Home

BinaryReader 中缺失的一些方法

starIconstarIconstarIconstarIconstarIcon

5.00/5 (12投票s)

2021 年 4 月 23 日

CPOL

1分钟阅读

viewsIcon

9731

BinaryReader 需要更好的方式来读取字符串和类型。这里提供一个快速且简单的解决方案

ReadFixedString

引言

也许只是为了证明我可以为你节省不到 5 分钟的时间,并换取一些有用的东西,给你吧。

BinaryReader 无法从流中读取固定长度或 ASCII 空字符结尾的字符串,这很不幸,因为很多文件都以这种方式存储字符串,无论好坏。此外,没有简单的方法可以读取整个结构中的数据,而无需读取每个单独的字段。

我最近再次实现了这个功能,因为似乎每次我这样做,代码都会被埋藏在某个地方,以至于重写它比找到它更容易。因此,这个技巧对我来说和你一样重要,尊敬的读者。

编写这个混乱的程序

这段代码非常短,我直接把它粘贴在这里供你使用。

using System;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;

/// <summary>
/// Provides some conspicuously absent string and type functionality to 
/// <seealso cref="BinaryReader"/>
/// </summary>
static class BinaryReaderExtensions
{
    /// <summary>
    /// Reads a class or a struct from the reader
    /// </summary>
    /// <typeparam name="T">The type to read</typeparam>
    /// <param name="reader">The reader</param>
    /// <returns>An instance of <typeparamref name="T"/> as read from the stream</returns>
    public static T ReadType<T>(this BinaryReader reader)
    {
        byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));

        GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
        T result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
        handle.Free();

        return result;
    }
    /// <summary>
    /// Reads a C style null terminated ASCII string
    /// </summary>
    /// <param name="reader">The binary reader</param>
    /// <returns>A string as read from the stream</returns>
    public static string ReadSZString(this BinaryReader reader)
    {
        var result = new StringBuilder();
        while (true)
        {
            byte b = reader.ReadByte();
            if (0 == b)
                break;
            result.Append((char)b);
        }
        return result.ToString();
    }
    /// <summary>
    /// Reads a fixed size ASCII string
    /// </summary>
    /// <param name="reader">The binary reader</param>
    /// <param name="count">The number of characters</param>
    /// <returns>A string as read from the stream</returns>
    public static string ReadFixedString(this BinaryReader reader,int count)
    {
        return Encoding.ASCII.GetString(reader.ReadBytes(count));
    }
}

使用这个烂摊子

将上述代码粘贴到你的代码文件后,只需像往常一样使用 BinaryReader,只是现在你有了上述方法。请记住,你想要从文件中读取的任何类型都必须能够被编组。这意味着你可能需要实际将编组属性添加到你的类型中,才能使用 ReadType<>() 与它们一起使用。

在处理使用固定长度或空字符终止的 ASCII 存储字符串的旧文件时,读取这些 ASCII 字符串通常很有用。当你在流中遇到这样的字符串时,只需使用适当的方法来读取它。文档注释应该使一切清晰明了。

就这样了。希望对你有所帮助,如果现在没有帮助,那么将来某个时候也会有帮助。

历史

  • 2021 年 4 月 23 日 - 初始提交
© . All rights reserved.