【C#】实用小技巧分享:在流指定位置写入字符文本

Stream中提供了在流开始/末尾处写入文本的方法。如下实现一个在流的指定位置写入文本的方法。

例:在下面文本的某指定位置写入字符文本

实现原理

获取想要写入的文本位置,把该位置后的所有文本+写入文本复制到另一byte数组中,最后用该byte数组重写后面的部分即完成“指定写入”的操作。

代码实现

步骤一:创建Stream流对象,获取文本的信息

步骤二:指定我们要查找的文本位置(例在以上文本的“微软公司”前写入文本),流不能直接操作字符串,所以把该字符串转为byte数组存储。

 

步骤三:根据提供的byte数组返回其在文本中所对应的流位置

 

此方法的核心来自网络查找,有些许改动。

参数一表示要搜索的流;

参数二表示流搜索的开始位置,一般从0开始;

参数三表示需要搜索位置的关键字

参数四表示要查找的第几个关键字(比如一个文本中有多个此关键字)

返回值是该关键字所在的流位置,未找到时返回-1

步骤四: 从当前返回的流位置开始,获取后面所有的文本内容,并把内容存放在byte数组中

步骤五:创建我们想要写入该位置的字符串(在“微软公司”前面写入“测试”),并把该字符串转换的byte数组和上面的数组内容合并。 (这里我是先把上面的数组转换成了字符串,再将字符串合并后转为的数组,可能麻烦了一点)

 

步骤六:在该位置后重写新建的流,完成指定写入操作。(流写入时会直接替换掉后面已有的内容) 

实现效果:

 

 如果你想插入位置的关键字有多个同名,更改Search方法的最后一个参数查找指定次数后的关键字即可。如需要完成写入时类似回车的操作,字符串加对应的转义字符即可。

 

 完整代码

 

  class Program
    {
        static void Main(string[] args)
        {
            string path = "temp.txt";
            using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite))
            {
                //查找指定的字符
                string findIndex = "微软公司";

                //把当前查找字符转换成byte数组
                byte[] byteIndex = MyStream.ToByteArray(findIndex);

                //在当前文本流中查找第1次查找到的指定byte数组的流位置
                //第二个参数是设置流开始查找的位置,默认从0开始。
                //第四个次数是第index次查找到的关键字
                long index = MyStream.Search(stream, 0, byteIndex, 1);

                //如果index返回-1则表示没有找到这个匹配字符,跳出。
                if (index == -1)
                {
                    stream.Close();
                    return;
                }

                //根据查找到的位置,新建一个和返回值后面所有内容的数量一致的byte数组
                byte[] bytes = new byte[stream.Length  - index];

                //把指针定位到当前查找到的流位置下,即让流从该位置开始查找
                stream.Seek(index , SeekOrigin.Begin);

                //根据流位置把剩余内容全部读取到新建的byte数组中
                stream.Read(bytes, 0, bytes.Length);

                //我们需要写入的字符
                string text = "测试";

                //新建一个新字符串,该字符串=自己写入的文本+索引后剩余的文本
                string res = text + MyStream.ToStr(bytes);

                //把该替换后的文本转化成byte数组保存
                bytes = MyStream.ToByteArray(res);

                //重新把指针定位到之前查找到的流位置下(因为read后指针位置会改变)
                stream.Seek(index , SeekOrigin.Begin);

                //写入重新整合后的文本,完成“替换”
                stream.Write(bytes, 0, bytes.Length);

                //释放流资源
                stream.Close();

            }
            Console.ReadLine();
        }

     
    }
   static class MyStream {
        /// <summary>
        /// byte数组转换为字符串
        /// </summary>
        /// <returns></returns>
        public static string ToStr(this byte[] arr)
        {
            return System.Text.Encoding.Default.GetString(arr);
        }
        /// <summary>
        /// 字符串转换成byte数组
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static byte[] ToByteArray(this string str)
        {
            return System.Text.Encoding.Default.GetBytes(str);
        }

        /// <summary>
        ///  在当前流中搜索指定的 byte[]
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="beginPosition">搜索开始位置,从0开始</param>
        /// <param name="key">搜索关键字</param>
        /// <param name="indexId">被查找的指定次数的关键字</param>
        /// <returns>如果存在则返回byte[]在流中指定索引次数出现的位置,否则返回 -1</returns>
        public static long Search(this Stream stream, long beginPosition, byte[] key, int indexId)
        {
            if (stream == null || stream.Length <= beginPosition)
                return -1;

            if (key == null || stream.Length < key.Length)
                return -1;

            long i = -1;
            long j = -1;
            int times = 1;
            int currentByte = int.MinValue;
            for (i = beginPosition; i < stream.Length; i++)
            {
                if (stream.Length < key.Length + i)
                    break;

                stream.Seek(i, SeekOrigin.Begin);
                for (j = 0; j < key.Length; j++)
                {
                    currentByte = stream.ReadByte();
                    if (currentByte != key[j])
                        break;
                }

                if (j == key.Length && times < indexId)
                {
                    ++times;
                }
                else if (j == key.Length && times == indexId)
                {
                    return i;
                }

                if (currentByte == -1 || times > indexId)
                    break;
            }
            return -1;

        }

   }

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值