构造BufferWriter和BufferReader实现高效的对象序列化和反序列化

2023-10-31

    在之前的文章讲术了如何设计一个简单的网络缓冲区和缓冲池,在.net网络应用中有一个普遍的问题就是如何把对象写入缓冲和从缓冲中读取数据还原对象.在这里会实现一个Writer和Reader方便地把信息写入缓冲区和从缓冲区读取;先看下Writer和Reader功能.

BufferWriter

 

View Code
public class BufferWriter : IDisposable
{
private IList<Buffer> mBuffers = new List<Buffer>(20);
public IList<Buffer> Buffers
{
get
{
return mBuffers;
}
}
public BufferWriter(System.Text.Encoding coding)
{
Coding = coding;


}
public Encoding Coding
{
get;
set;
}
public void Dispose()
{
foreach (Buffer item in mBuffers)
{
item.Dispose();
}
mBuffers.Clear();
}
public void Write(byte value)
{
Write(new byte[] { value });
}
public void Write(DateTime datetime)
{
Write(BitConverter.GetBytes(datetime.Ticks));
}
private bool WriteArrayLength(Array value)
{
if (value == null)
{
Write(BitConverter.GetBytes(0));

}
else
{
Write(BitConverter.GetBytes(value.Length));
}
return value != null && value.Length > 0;
}
public void WriteDataTimeArray(DateTime[] value)
{
if (WriteArrayLength(value))
{
for (int i = 0; i < value.Length; i++)
{
Write(value[i]);
}
}
}
public void Write(float value)
{
Write(BitConverter.GetBytes(value));
}
public void WriteFloatArray(float[] value)
{
if (WriteArrayLength(value))
{
for (int i = 0; i < value.Length; i++)
{
Write(value[i]);
}
}
}
public void Write(bool value)
{
Write(BitConverter.GetBytes(value));
}
public void WriteBoolArray(bool[] value)
{
if (WriteArrayLength(value))
{
for (int i = 0; i < value.Length; i++)
{
Write(value[i]);
}
}
}
public void Write(char value)
{
Write(BitConverter.GetBytes(value));
}
public void WriteCharArray(char[] value)
{
if (WriteArrayLength(value))
{
for (int i = 0; i < value.Length; i++)
{
Write(value[i]);
}
}
}
public void Write(double value)
{
Write(BitConverter.GetBytes(value));
}
public void WriteDoubleArray(double[] value)
{
if (WriteArrayLength(value))
{
for (int i = 0; i < value.Length; i++)
{
Write(value[i]);
}
}
}
public void Write(Int16 value)
{
Write(BitConverter.GetBytes(value));
}
public void WriteInt16Array(Int16[] value)
{
if (WriteArrayLength(value))
{
for (int i = 0; i < value.Length; i++)
{
Write(value[i]);
}
}
}
public void Write(Int32 value)
{
Write(BitConverter.GetBytes(value));
}
public void WriteInt32Array(Int32[] value)
{
if (WriteArrayLength(value))
{
for (int i = 0; i < value.Length; i++)
{
Write(value[i]);
}
}
}
public void Write(Int64 value)
{
Write(BitConverter.GetBytes(value));
}
public void WriteInt64Array(Int64[] value)
{
if (WriteArrayLength(value))
{
for (int i = 0; i < value.Length; i++)
{
Write(value[i]);
}
}
}
public void Write(string value)
{
Write(Coding.GetBytes(value));
}
public void WriteBlock(string value)
{
if (string.IsNullOrEmpty(value))
{
Write(0);

}
else
{
byte[] data = Coding.GetBytes(value);
Write(data.Length);
Write(data);
}
}
public void WriteBlockArray(string[] value)
{
if (WriteArrayLength(value))
{
for (int i = 0; i < value.Length; i++)
{
WriteBlock (value[i]);
}
}
}
public void WriteObject(IMessage obj)
{
obj.Save(this);
}
public void WriteObjects<T>(IList<T> objs) where T:IMessage
{
if (objs == null)
{
Write(0);
return;
}
Write(objs.Count);
for (int i = 0; i < objs.Count; i++)
{
WriteObject(objs[i]);
}

}
public void Write(byte[] value)
{
mBuffers.Add(new Buffer(value));

}
}

 

BufferReader

View Code
public class BufferReader : IDisposable
{
private IList<Buffer> mBuffers;
private int mIndex = 0;
private Buffer mCursorBuffer;
public BufferReader(Encoding coding, IList<Buffer> buffers)
{
mBuffers = buffers;
Coding = coding;
foreach (Buffer item in mBuffers)
{
item.Reset();
}
nextBuffer();
}
public BufferReader(Encoding coding, BufferWriter write)
{
Coding = coding;
mBuffers = write.Buffers;
foreach (Buffer item in mBuffers)
{
item.Reset();
}
nextBuffer();
}
public Encoding Coding
{
get;
set;
}
private void nextBuffer()
{
mCursorBuffer = mBuffers[mIndex];
mIndex++;
}
public ArraySegment<byte> Read(int count)
{

ArraySegment<byte> result = mCursorBuffer.Read(count);
if (result.Count == count)
return result;
int readcount = 0;
byte[] data = new byte[count];
while (true)
{

Array.Copy(result.Array, result.Offset, data, readcount, result.Count);
readcount += result.Count;
if (readcount >= count)
break;
nextBuffer();
result = mCursorBuffer.Read(count - readcount);
}
return new ArraySegment<byte>(data, 0, count);

}
private T[] createArray<T>()
{
T[] result = new T[ReadInt32()];
return result;

}
public bool ReadBool()
{
ArraySegment<byte> data = Read(1);
bool result = BitConverter.ToBoolean(data.Array, data.Offset);
return result;
}
public bool[] ReadBoolArray()
{
bool[] result = createArray<bool>();
for (int i = 0; i < result.Length; i++)
{
result[i] = ReadBool();
}
return result;
}
public char ReadChar()
{
ArraySegment<byte> data = Read(2);
char result = BitConverter.ToChar(data.Array, data.Offset);

return result;
}
public char[] ReadCharArray()
{
char[] result = createArray<char>();
for (int i = 0; i < result.Length; i++)
{
result[i] = ReadChar();
}
return result;
}
public double ReadDouble()
{
ArraySegment<byte> data = Read(8);
double result = BitConverter.ToDouble(data.Array, data.Offset);

return result;
}
public double[] ReadDoubleArray()
{
double[] result = createArray<double>();
for (int i = 0; i < result.Length; i++)
{
result[i]=ReadDouble();
}
return result;
}
public Int16 ReadInt16()
{
ArraySegment<byte> data = Read(2);
Int16 result = BitConverter.ToInt16(data.Array, data.Offset);

return result;
}
public Int16[] ReadInt16Array()
{
Int16[] result = createArray<Int16>();
for (int i = 0; i < result.Length; i++)
{
result[i] = ReadInt16();
}
return result;
}
public Int32 ReadInt32()
{
ArraySegment<byte> data = Read(4);
Int32 result = BitConverter.ToInt32(data.Array, data.Offset);

return result;
}
public Int32[] ReadInt32Array()
{
Int32[] result = createArray<Int32>();
for (int i = 0; i < result.Length; i++)
{
result[i] = ReadInt32();
}
return result;
}
public Int64 ReadInt64()
{
ArraySegment<byte> data = Read(8);
Int64 result = BitConverter.ToInt64(data.Array, data.Offset);

return result;
}
public Int64[] ReadInt64Array()
{
Int64[] result = createArray<Int64>();
for (int i = 0; i < result.Length; i++)
{
result[i] = ReadInt64();
}
return result;
}
public float ReadFloat()
{
ArraySegment<byte> data = Read(4);
Single result = BitConverter.ToSingle(data.Array, data.Offset);

return result;
}
public float[] ReadFloatArray()
{
float[] result = createArray<float>();
for (int i = 0; i < result.Length; i++)
{
result[i] = ReadFloat();
}
return result;
}
public DateTime ReadDateTime()
{
long date = ReadInt64();
return new DateTime(date);
}
public DateTime[] ReadDateTimeArray()
{
DateTime[] result = createArray<DateTime>();
for (int i = 0; i < result.Length; i++)
{
result[i] = ReadDateTime();
}
return result;
}
public string ReadBlock()
{
int length = ReadInt32();
if (length > 0)
return ReadString(length);
return null;
}
public string[] ReadBlockArray()
{
string[] result = createArray<string>();
for (int i = 0; i < result.Length; i++)
{
result[i] = ReadBlock();
}
return result;
}
public T ReadObject<T>() where T : IMessage,new()
{
T item = new T();
item.Load(this);
return item;
}
public IList<T> ReadObjects<T>() where T : IMessage, new()
{
List<T> items = new List<T>();
int count = ReadInt32();
for (int i = 0; i < count; i++)
{
items.Add(ReadObject<T>());
}
return items;

}
public string ReadString(int count)
{
ArraySegment<byte> data = Read(count);
string result = Coding.GetString(data.Array, data.Offset, count);
return result;
}
public void Dispose()
{
foreach (Buffer item in mBuffers)
{
item.Dispose();
}
mBuffers.Clear();
}
}

 

以上两个对象的方法都是基于BitConverter进行基础类型的处理,即方便又高效;但这样会存在一个问题就是不能处理复杂的对象,对于复杂的对象可以采用规则约束的方式来处理;如果对asp.net的ViewState有了解的同学们应该知道有一个IStateManager接口用于对象自定义ViewState存取用的.其实可以直接采用这种方式来给对象进行处理.首先制定一个接口:

public interface IMessage
    {
        void Load(BufferReader reader);
        void Save(BufferWriter writer);
    }

实现以上接口实现一个简单自定义序列化对象功能

public class User : IMessage
        {
            public User()
            {
                Accunts = new List<Account>();
            }
            public string Name
            {
                get;
                set;
            }
            public string EMail
            {
                get;
                set;
            }
            public string City
            {
                get;
                set;
            }
            public DateTime Birthdate
            {
                get;
                set;
            }
            public void Load(BufferReader reader)
            {
                Name = reader.ReadBlock();
                EMail = reader.ReadBlock();
                City = reader.ReadBlock();
                Birthdate = reader.ReadDateTime();
                Accunts = reader.ReadObjects<Account>();
            }
            public void Save(BufferWriter writer)
            {
                writer.WriteBlock(Name);
                writer.WriteBlock(EMail);
                writer.WriteBlock(City);
                writer.Write(Birthdate);
                writer.WriteObjects<Account>(Accunts);
               
            }
}

把对象写入缓冲区 

           User user = new User();
            user.Name = "henryfan";
            user.City = "GuangZhou";
            user.EMail = "henryfan@msn.com";
            user.Birthdate = DateTime.Now;
            BufferWriter writer = new BufferWriter(Encoding.UTF8);
            user.Save(writer);

从缓冲区读取对象

           User nuser = new User();
            BufferReader reader = new BufferReader(Encoding.UTF8, writer);
            nuser.Load(reader);

以上只是一个简单的对象,下面是构造一个相对复杂点的

public class User : IMessage
        {
            public User()
            {
                Accunts = new List<Account>();
            }
            public string Name
            {
                get;
                set;
            }
            public string EMail
            {
                get;
                set;
            }
            public string City
            {
                get;
                set;
            }
            public DateTime Birthdate
            {
                get;
                set;
            }
            public void Load(BufferReader reader)
            {
                Name = reader.ReadBlock();
                EMail = reader.ReadBlock();
                City = reader.ReadBlock();
                Birthdate = reader.ReadDateTime();
                Accunts = reader.ReadObjects<Account>();
            }
            public void Save(BufferWriter writer)
            {
                writer.WriteBlock(Name);
                writer.WriteBlock(EMail);
                writer.WriteBlock(City);
                writer.Write(Birthdate);
                writer.WriteObjects<Account>(Accunts);
               
            }
            public IList<Account> Accunts
            {
                get;
                set;
            }
            public class Account:IMessage
            {
                public Account()
                {
                    Items = new List<History>();
                }
                public string ID { get; set; }
                public double Money { get; set; }

                public IList<History> Items
                {
                    get;
                    set;
                }
                public void Load(BufferReader reader)
                {
                    ID = reader.ReadBlock();
                    Money = reader.ReadDouble();
                    Items = reader.ReadObjects<History>();
                }

                public void Save(BufferWriter writer)
                {
                    writer.WriteBlock(ID);
                    writer.Write(Money);
                    writer.WriteObjects<History>(Items);
                }
            }
            public class History:IMessage
            {
                public string ID
                {
                    get;
                    set;
                }
                public string Type
                {
                    get;
                    set;
                }
                public double Money
                {
                    get;
                    set;
                }
                public DateTime LastChangeDate
                {
                    get;
                    set;
                }


                public void Load(BufferReader reader)
                {
                    ID = reader.ReadBlock();
                    Type = reader.ReadBlock();
                    Money = reader.ReadDouble();
                    LastChangeDate = reader.ReadDateTime();
                }

                public void Save(BufferWriter writer)
                {
                    writer.WriteBlock(ID.ToString());
                    writer.WriteBlock(Type);
                    writer.Write(Money);
                    writer.Write(LastChangeDate);
                }
            }
        }

简单性能测试

以下在一台I5的电脑上做简单的性能测试,编译Release后执行相关程序

测试1

        static void test1()
        {
            User user = new User();
            user.Name = "henryfan";
            user.City = "GuangZhou";
            user.EMail = "henryfan@msn.com";
            user.Birthdate = DateTime.Now;
          

            for (int i = 0; i < 500000; i++)
            {

                BufferWriter writer = new BufferWriter(Encoding.UTF8);
                user.Save(writer);
                User nuser = new User();
                BufferReader reader = new BufferReader(Encoding.UTF8, writer);
                nuser.Load(reader);
            }
        }

耗时:976.7241(ms)

测试2

        static void test()
        {
            User user = new User();
            user.Name = "henryfan";
            user.City = "GuangZhou";
            user.EMail = "henryfan@msn.com";
            user.Birthdate = DateTime.Now;
            user.Accunts.Add(new User.Account { ID = "ac1", Money = 5 });
            user.Accunts[0].Items.Add(new User.History { ID = Guid.NewGuid().ToString(), LastChangeDate = DateTime.Now, Money = 50, Type = "BBQ" });
            user.Accunts[0].Items.Add(new User.History { ID = Guid.NewGuid().ToString(), LastChangeDate = DateTime.Now, Money = 34, Type = "BBE" });
            user.Accunts[0].Items.Add(new User.History { ID = Guid.NewGuid().ToString(), LastChangeDate = DateTime.Now, Money = 44, Type = "DDEQ" });
            
            for (int i = 0; i <500000; i++)
            {
                
                BufferWriter writer = new BufferWriter(Encoding.UTF8);
                user.Save(writer);
                User nuser = new User();
                BufferReader reader = new BufferReader(Encoding.UTF8, writer);
                nuser.Load(reader);
            }
        }

耗时:4119.8927(ms)

以上的实现也只是对之前文章提到的缓冲区使用,并没有用到池.对于如何使用池相信兴趣的同学来说没什么问题,需要的就从池中拿,用完就回收就是了.

转载于:https://www.cnblogs.com/smark/archive/2011/11/02/2232892.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

构造BufferWriter和BufferReader实现高效的对象序列化和反序列化 的相关文章

  • lib库知识全面讲解(.lib、.dll)

    一 静态链接lib库和lib导入库以及动态链接库dll的关系 lib静态库 和 导入lib库 这些词汇相信我们经常听说了吧 但是lib怎么来的 怎么使用的我们很多人还真不知道哦 我也是专门研究学习才发现的 所以在此详细讲述下 分享给大家 想
  • 华为OD机试 - 喊7的次数重排(Java)

    题目描述 喊7是一个传统的聚会游戏 N个人围成一圈 按顺时针从1到N编号 编号为1的人从1开始喊数 下一个人喊的数字为上一个人的数字加1 但是当将要喊出来的数字是7的倍数或者数字本身含有7的话 不能把这个数字直接喊出来 而是要喊 过 假定玩
  • 龙芯 buildroot 使用详解

    龙芯 buildroot 使用详解 一般文件系统都要包含很多第三方软件 如 busybox tftp apache PHP DNS qt等等 为了避免繁琐的移植工作 buildroot应运而生 通过menuconfig来配置我们需要的功能
  • 基于Golang的gRPC框架使用与开发

    一 gRPC 基础 包括 rpc gRPC Protobuf 等概念 网上已经有详细的介绍 此处不再过多说明 关于 gRPC 的介绍 可以参考官方介绍文档 以及微软官方文档介绍 通俗的来说 gRPC 是一种 rpc 的具体实现 其利用 Pr
  • 五、STL容器:STL算法总结

    5 STL算法 5 1 构成 头文件 功能
  • 从被吐槽的Amazon看,如何建设好的on call机制?

    对于每个程序员来说 进入市值万亿的Amazon工作 似乎都是一件值得骄傲的事 但只要在网络上一提起Amazon 关于它的on call 机制的吐槽就会此起彼伏 要知道在互联网公司 on call应该是非常普遍的现象 但大家为什么对Amazo
  • 职工管理系统(超详细版c++)

    一 项目概述 编写一个有添加 删除 修改 显示 排序 查找功能的职工管理系统 对一些职工的信息进行处理 保存到文本文件中 便于后续使用 二 创建项目 在本篇文章中我们使用vs2022版本编写程序 为了使我们的代码结构严谨 减少冗余 便于修改
  • 我从未结束的Java之旅(二)

    目录 大胆北漂 餐饮 团队扩张 扩张的烦恼 团队管理的探索 大胆北漂 餐饮 团队扩张 由于公司业务的扩展以及战略方向的变更 之前负责得小团队不得不扩招 由5个人得团队补充到了20人 当时我们saas服务已经很庞大了 基本涉及到餐饮相关的所有
  • Go语言之JSON解码函数Unmarshal

    直接上代码 package main import encoding json fmt 定义Actress结构体 type Actress struct Name string Birthday string BirthPlace stri
  • springboot 之 JPA

    一 说明 JPA提供了操作数据库的接口 在开发过程中继承和使用这些接口 可简化现有的持久化开发的工作 二 JPA提供的接口 1 JpaRepository JpaRepository继承自PagingAndSortingRepository
  • P1541 [NOIP2010 提高组] 乌龟棋(dp)dp5

    https www luogu com cn problem P1541 include
  • 【MySQL】表的内外连接

    需要云服务器等云产品来学习Linux的同学可以移步 gt 腾讯云 lt gt 阿里云 lt gt 华为云 lt 官网 轻量型云服务器低至112元 年 新用户首次下单享超低折扣 目录 一 内连接 表1 inner join 表2 on 1 显
  • DBNN实验进展

    实验环境 cpu version 1 Precsion Recall f1 scorem precision of mbnn is 0 8756 recall of mbnn is 0 8670 f1 score of mbnn is 0
  • 元宇宙(四)ROBLOX

    至2019年 已有超过500万的青少年开发者使用Roblox开发3D VR等数字内容 吸引的月活跃玩家超1亿 Roblox在玩法上进一步创新升级 类型更全面 除了传统的探索建造类沙盒玩法外 Roblox还覆盖主流的角色扮演 第一人称射击 动
  • 第9届Python编程挑战赛北京赛区复赛真题剖析-2023年全国青少年信息素养大赛

    导读 超平老师计划推出 全国青少年信息素养大赛Python编程真题解析 50讲 这是超平老师解读Python编程挑战赛系列的第16讲 全国青少年信息素养大赛 原全国青少年电子信息智能创新大赛 是 世界机器人大会青少年机器人设计与信息素养大赛
  • 不同格式点云存储结构(txt、pcd、las、ply)整理以及基本的读写、可视化方法

    不同格式点云存储结构整理以及基本的读写 可视化方法 一 文本 txt 1 1 存储结构 1 2 读取 二 PCD格式 1 1 存储结构 1 2 读写 1 2 1 open3d读写 python 1 2 2 PCL读写 C 三 LAS格式 3
  • 基于马尔可夫链的写作机器人软件

    数据结构课设 二 作业要求 设计并实现一个基于马尔可夫链的写作机器人软件 软件通过对素材文本的学习 建立词库以及单词的马尔可夫链 然后使用所建立的单词马尔可夫链配合随机数选择 自动生成一段文字 分析 由于不太清楚老师的具体要求 所以在网上找
  • 微信小程序如何根据不同用户切换不同TabBar

    现有需求 小程序用户有三种身份 公众 运维人员 领导 根据不同用户身份显示不同的tabbar 众所周知微信小程序全局文件app json里面的 tabBar 里面的list只能放置2 5个 要想实现3个tabbar 必须得复用tabbar
  • 回归分析详解及matlab实现

    当人们对研究对象的内在特性和各因素间的关系有比较充分的认识时 一般用机理分析方法建立数学模型 如果由于客观事物内部规律的复杂性及人们认识程度的限制 无法分析实际对象内在的因果关系 建立合乎机理规律的数学模型 那么通常的办法是搜集大量数据 基
  • 惊!STM32 蓝牙串口模块(H21/JDY-31) 竟如此简单!

    惊 STM32 蓝牙串口模块 H21 JDY 31 竟如此简单 文章日志 1 写于2022 08 19 文章目录 1 认识蓝牙串口模块 2 困扰我很久的实验竟如此简单 3 一些现象的思考 1 认识蓝牙串口模块 JDY 31 蓝牙基于蓝牙 3

随机推荐

  • sql服务器显示空白,sql服务器空白

    sql服务器空白 内容精选 换一换 登录Windows操作系统的裸金属服务器时 需使用密码方式登录 因此 用户需先根据创建裸金属服务器时使用的密钥文件 获取该裸金属服务器初始安装时系统生成的管理员密码 Administrator帐户或Clo
  • 剑指 Offer 50. 第一个只出现一次的字符

    剑指 Offer 50 第一个只出现一次的字符 题目 题目链接 具体代码 集合缓存法 索引比较法 题目 题目链接 https leetcode cn com problems di yi ge zhi chu xian yi ci de z
  • linux线程私有数据详解

    在单线程程序中 函数经常使用全局变量或静态变量 这是不会影响程序的正确性的 但如果线程调用的函数使用全局变量或静态变量 则很可能引起编程错误 因为这些函数使用的全局变量和静态变量无法为不同的线程保存各自的值 而当同一进程内的不同线程几乎同时
  • Qt:提示框类型使用

    一 默认提示框 注意 使用前需要导入相应库 include
  • 私有构造函数

    通常我们都将构造函数的声明置于public区段 假如我们将其放入private区段中会发生什么样的后果 没错 我也知道这将会使构造函数成为私有的 这意味着什么 我们知道 当我们在程序中声明一个对象时 编译器为调用构造函数 如果有的话 而这个
  • 天线的π型电路作用

    天线的 型电路作用 天线阻抗匹配的意义 常见的WiFi或者蓝牙天线都有 型电路 主要是做阻抗匹配的 起初以为是解决EMI的问题 后来才知是阻抗匹配的 其目的就是实现功率的最大传输 让天线的指标达到最好状态 阻抗匹配的基本原理 以纯电阻阻抗电
  • hiredis发布/订阅示例

    转 http www xuebuyuan com 950148 html include
  • 什么是obj文件?

    百度百科 程序编译时生成的中间代码文件 目标文件 一般是程序编译后的二进制文件 再通过链接器 LINK EXE 和资源文件链接就成可执行文件了 OBJ只给出了程序的相对地址 而可执行文件是绝对地址 1 这个问题不是很简单 你只看到了文件从源
  • rename函数的用法

    import pandas as pd df pd DataFrame A 1 2 3 B 4 5 6 print df df1 df rename columns A a B c print df1 结果 A B 0 1 4 1 2 5
  • tensorflow的Data Pipeline系列教程(一)——Dataset类的属性即常用方法

    前言 在tensorflow中 训练数据常常需要经过随机打乱 分成一个一个的batch来进行训练 当然有很多的方式可以完成 比如我们可以通过传统的python方法构建迭代器 我们也可以使用其它的一些方法 但是tensorflow本身提供了强
  • 2.管理者的分类与角色

    管理者及其分类 什么是管理者 管理者是组织中那些指挥别人活动的人 管理者工作绩效的好坏直接关系着组织的兴衰成败 管理者处于组织中的不同层次 其头衔也各式各样 但他们工作具有一个共同的特征 即都是通过协调他人的努力来是组织活动更加有效并实现组
  • 328. 奇偶链表-链表拆分合并

    一 题目描述 给定单链表的头节点 head 将所有索引为奇数的节点和索引为偶数的节点分别组合在一起 然后返回重新排序的列表 第一个节点的索引被认为是 奇数 第二个节点的索引为 偶数 以此类推 请注意 偶数组和奇数组内部的相对顺序应该与输入时
  • 坏苹果是团队的毒药

    最近一期的 美国生活 采访了WillFelps 他是华盛顿大学的一位教授 曾经组织过一次社会学实验来证明 坏苹果 的出奇强大的影响力 译者注 美国生活 This American Life 是一档叙事类的广播节目 每周一期 在超过500家电
  • ubuntu10.04和12.04 上cpan的安装步骤及常见问题解决方法

    在我们用 perl 编写程序的时候 会要用到很多的 perl module 这种情况下就需要安装程序所需要的 module 然而这些module通常都是在www cpan org网站上面抓的 所以我们可以通过安装cpan来安装perl程序需
  • mysql 备忘录

    文章目录 rownum 版本 DDL DML insert insert into x with recursive mysql8 0 临时表 常用 存储过程 数据导出 导入 mysqldump load data csv 比 insert
  • Go语言并发之美:解释其中内核、外延

    多核处理器越来越普及 那有没有一种简单的办法 能够让我们写的软件释放多核的威力 答案是 Yes 随着Golang Erlang Scale等为并发设计的程序语言的兴起 新的并发模式逐渐清晰 正如过程式编程和面向对象一样 一个好的编程模式需要
  • 短信消息通知服务-spring定时计划任务quartz(一)

    集成短信消息与平台服务 希望能够在工作台中的每天的值班计划安排表中获取相关数据通知到每个当天值班人员 达到消息的畅通及时性 当中涉及到的技术有spring quartz等 具体步骤如下 一 编写业务类 package com greedc
  • 在微信小程序中怎样阻止冒泡事件?

    在微信小程序当中 当两个包含的视图都使用了bindtap函数来绑定点击事件的话 就会发生冒泡事件 即点击内部事件时将同时触发外部事件 如果我们要想阻止冒泡事件的发生 将被包含在内部的bindtap该为catchtap即可 下面请看具体事例
  • win10远程连接win7 使用win自带远程连接

    1 右键计算机打开属性 2 点击高级设置 3 勾选容许连接 确定 4 win r 打开运行输入cmd 5 查看机器ip地址 6 在另一台电脑打开远程连接 6 打开之后输入刚才查看的IP地址 7 输入用户名和密码 如果没有就在被连接的电脑创建
  • 构造BufferWriter和BufferReader实现高效的对象序列化和反序列化

    在之前的文章讲术了如何设计一个简单的网络缓冲区和缓冲池 在 net网络应用中有一个普遍的问题就是如何把对象写入缓冲和从缓冲中读取数据还原对象 在这里会实现一个Writer和Reader方便地把信息写入缓冲区和从缓冲区读取 先看下Writer