如何删除存在于某些文本内的任何UTF-8 BOM,而不是在某些文本的开头

本文关键字:文本 BOM 开头 UTF-8 任何 删除 存在 于某些 何删除 | 更新日期: 2023-09-27 18:17:23

我们收到一些文件,这些文件是由另一方连接的。在这些文件的中间是一些BOM字符。

是否有一种方法可以检测到这3个字符并删除它们?我已经看到了很多关于如何从文件开头删除BOM的例子…

如何删除存在于某些文本内的任何UTF-8 BOM,而不是在某些文本的开头

假设您的文件足够小,可以保存在内存中,并且您有一个Enumerable.Replace扩展方法来替换子序列,那么您可以使用:

var bytes = File.ReadAllBytes(filePath);
var bom = new byte[] { 0xEF, 0xBB, 0xBF };
var empty = Enumerable.Empty<byte>();
bytes = bytes.Replace(bom, empty).ToArray();
File.WriteAllBytes(filePath, bytes);
下面是Replace扩展方法的一个简单(低效)实现:
public static IEnumerable<TSource> Replace<TSource>(
    this IEnumerable<TSource> source,
    IEnumerable<TSource> match,
    IEnumerable<TSource> replacement)
{
    return Replace(source, match, replacement, EqualityComparer<TSource>.Default);
}
public static IEnumerable<TSource> Replace<TSource>(
    this IEnumerable<TSource> source,
    IEnumerable<TSource> match,
    IEnumerable<TSource> replacement,
    IEqualityComparer<TSource> comparer)
{
    int sLength = source.Count();
    int mLength = match.Count();
    if (sLength < mLength || mLength == 0)
        return source;
    int[] matchIndexes = (
        from sIndex in Enumerable.Range(0, sLength - mLength + 1)
        where source.Skip(sIndex).Take(mLength).SequenceEqual(match, comparer)
        select sIndex
    ).ToArray();
    var result = new List<TSource>();
    int sPosition = 0;
    foreach (int mPosition in matchIndexes)
    {
        var sPart = source.Skip(sPosition).Take(mPosition - sPosition);
        result.AddRange(sPart);
        result.AddRange(replacement);
        sPosition = mPosition + mLength;
    }
    var sLastPart = source.Skip(sPosition).Take(sLength - sPosition);
    result.AddRange(sLastPart);
    return result;
}