本文将带您了解关于通过Zoopkeeper-BinaryOutputArchive类学习utf-8的实现的新内容,同时我们还将为您解释zooconservationprogrammes解析的相关知识,
本文将带您了解关于通过Zoopkeeper-BinaryOutputArchive类学习utf-8的实现的新内容,同时我们还将为您解释zoo conservation programmes解析的相关知识,另外,我们还将为您提供关于Angular2的input和output(原先的properties和events)、Array.ConvertAll
- 通过Zoopkeeper-BinaryOutputArchive类学习utf-8的实现(zoo conservation programmes解析)
- Angular2的input和output(原先的properties和events)
- Array.ConvertAll
数组相互转化方法 - boost :: archive :: binary_oarchive =程序崩溃?
- Cannot set the value of read-only property ''outputFile'' for ApkVariantOutputImpl_Dec
通过Zoopkeeper-BinaryOutputArchive类学习utf-8的实现(zoo conservation programmes解析)
BinaryOutputArchive类位于org.apache.jute包中,是序列化组件中的一个类。从字面意思理解就是输出类。这里类实现了OutputArchive接口。并且在构造函数中需要传递一个DataOutput接口的实现类。
在这个代码中有一段代码引起了我的注意:
/**
* create our own char encoder to utf8. This is faster
* then string.getbytes(UTF8).
* @param s the string to encode into utf8
* @return utf8 byte sequence.
*/
final private ByteBuffer stringToByteBuffer(CharSequence s) {
bb.clear();
final int len = s.length();
for (int i = 0; i < len; i++) {
if (bb.remaining() < 3) {
ByteBuffer n = ByteBuffer.allocate(bb.capacity() << 1);
bb.flip();
n.put(bb);
bb = n;
}
char c = s.charAt(i);
//一个字节
if (c < 0x80) {
bb.put((byte) c);
}
else if (c < 0x800) {
bb.put((byte) (0xc0 | (c >> 6)));
bb.put((byte) (0x80 | (c & 0x3f)));
} else {
bb.put((byte) (0xe0 | (c >> 12)));
bb.put((byte) (0x80 | ((c >> 6) & 0x3f)));
bb.put((byte) (0x80 | (c & 0x3f)));
}
}
bb.flip();
return bb;
}
根据代码的注释说这里的实现比java自身的要高效。那么究竟是怎么样呢?值得对比进行学习一番。
首先在对比之前要先弄清除他们在做什么。这里的方式实现了一个字符串转化正一个utf-8编码格式的字节数组。那么utf-8编码格式是规定怎么进行转换的呢?大体的规则如下:
1.对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2.对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
实例如下:
一个字节 0000 0000-0000 007F | 0xxxxxxx
两个字节 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
三个字节 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
四个字节 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
根据上面的规则再去理解代码就方便一些了。stringToByteBuffer方法的逻辑大致是:
循环字符的长度。如果缓冲字节类ByteBuffer 的剩余空间不足则扩充1倍。(这里使用了位运算)
如果是1个字节直接保存
如果是2个字节,先把字符的前一部分根据规则放入第一个字节中,然后把后面一部分放入第二个字节中。0xc0-->11000000。用它或一个字符刚好满足上面规则中110xxxxx的要求。代码 c >> 6 让我理解了好半天(可能是我比较笨的原因吧)。最后我发现根据规则除了第一个字节,其他字节都是前两位为10.那么就只剩下6位了。所以移位计算的数字是以6的倍数来进行的。0x80-->10000000、0x3f-->00111111。代码 0x80 | (c & 0x3f) 刚好满足了第二个字节的条件
3字节的代码和2字节的代码比较类似
理解了stringToByteBuffer这个方法之后,我们再来看看java中的实现:
public byte[] getBytes(String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null) throw new NullPointerException();
return StringCoding.encode(charsetName, value, 0, value.length);
}
没什么好说的,调用了一个StringCoding的一个方法。继续跟踪代码:
static byte[] encode(String charsetName, char[] ca, int off, int len)
throws UnsupportedEncodingException
{
StringEncoder se = deref(encoder);
String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
if ((se == null) || !(csn.equals(se.requestedCharsetName())
|| csn.equals(se.charsetName()))) {
se = null;
try {
Charset cs = lookupCharset(csn);
if (cs != null)
se = new StringEncoder(cs, csn);
} catch (IllegalCharsetNameException x) {}
if (se == null)
throw new UnsupportedEncodingException (csn);
set(encoder, se);
}
return se.encode(ca, off, len);
}
这段代码的大概的意思猜测是,先根据传递的字符集名称去查找字符集,然后根据字符集创建一个StringEncoder类型的对象。然后调用对象的encode方法。继续跟踪代码:
byte[] encode(char[] ca, int off, int len) {
int en = scale(len, ce.maxBytesPerChar());
byte[] ba = new byte[en];
if (len == 0)
return ba;
if (ce instanceof ArrayEncoder) {
int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
return safeTrim(ba, blen, cs, isTrusted);
} else {
ce.reset();
ByteBuffer bb = ByteBuffer.wrap(ba);
CharBuffer cb = CharBuffer.wrap(ca, off, len);
try {
CoderResult cr = ce.encode(cb, bb, true);
if (!cr.isUnderflow())
cr.throwException();
cr = ce.flush(bb);
if (!cr.isUnderflow())
cr.throwException();
} catch (CharacterCodingException x) {
// Substitution is always enabled,
// so this shouldn''t happen
throw new Error(x);
}
return safeTrim(ba, bb.position(), cs, isTrusted);
}
}
这段代码判断StringEncoder的类型。我写个测试用例byte[] x="a".getbytes("utf-8"); 跟踪代码到这里发现走的是 ArrayEncoder这里逻辑。继续跟踪发现ArrayEncoder有多个实现。其中有一个UTF_8类。这个类在nio包中。这里的代码只能通过反编译来看,没有找到源码包:
/* */ public int encode(char[] paramArrayOfChar, int paramInt1, int paramInt2, byte[] paramArrayOfByte)
/* */ {
/* 627 */ int i = paramInt1 + paramInt2;
/* 628 */ int j = 0;
/* 629 */ int k = j + Math.min(paramInt2, paramArrayOfByte.length);
/* 632 */ while ((j < k) && (paramArrayOfChar[paramInt1] < '''')) {
/* 633 */ paramArrayOfByte[(j++)] = ((byte)paramArrayOfChar[(paramInt1++)]);
/* */ }
/* 635 */ while (paramInt1 < i)
/* */ {
/* 636 */ char c = paramArrayOfChar[(paramInt1++)];
/* 637 */ if (c < ''-'')
/* */ {
/* 639 */ paramArrayOfByte[(j++)] = ((byte)c);
/* */ }
/* 640 */ else if (c < ''ࠀ'')
/* */ {
/* 642 */ paramArrayOfByte[(j++)] = ((byte)(0xC0 | c >> ''\006''));
/* 643 */ paramArrayOfByte[(j++)] = ((byte)(0x80 | c & 0x3F));
/* */ }
/* 644 */ else if (Character.isSurrogate(c))
/* */ {
/* 645 */ if (this.sgp == null) {
/* 646 */ this.sgp = new Surrogate.Parser();
/* */ }
/* 647 */ int m = this.sgp.parse(c, paramArrayOfChar, paramInt1 - 1, i);
/* 648 */ if (m < 0)
/* */ {
/* 649 */ if (malformedInputAction() != CodingErrorAction.REPLACE) {
/* 650 */ return -1;
/* */ }
/* 651 */ paramArrayOfByte[(j++)] = replacement()[0];
/* */ }
/* */ else
/* */ {
/* 653 */ paramArrayOfByte[(j++)] = ((byte)(0xF0 | m >> 18));
/* 654 */ paramArrayOfByte[(j++)] = ((byte)(0x80 | m >> 12 & 0x3F));
/* 655 */ paramArrayOfByte[(j++)] = ((byte)(0x80 | m >> 6 & 0x3F));
/* 656 */ paramArrayOfByte[(j++)] = ((byte)(0x80 | m & 0x3F));
/* 657 */ paramInt1++;
/* */ }
/* */ }
/* */ else
/* */ {
/* 661 */ paramArrayOfByte[(j++)] = ((byte)(0xE0 | c >> ''\f''));
/* 662 */ paramArrayOfByte[(j++)] = ((byte)(0x80 | c >> ''\006'' & 0x3F));
/* 663 */ paramArrayOfByte[(j++)] = ((byte)(0x80 | c & 0x3F));
/* */ }
/* */ }
/* 666 */ return j;
/* */ }
和zookeeper中的差不多,都是在用位运算来实现utf-8的规则。
对比代码的理解如下:
zookeeper中实现了3字节的转换,而java的类实现了4字节的转换。
代码复杂度上java的比zookeeper要高
直观上我没有发现具体的实现上zookeeper会比较高。
到这里utf-8的实现就完毕了,但这里引起了我的思考:
zookeeper为什么需要自己去实现序列化、实现utf-8的转换
如果自己去开发一个分布式的系统是否也需要实现这些呢
也许等我在不断的学习zookeeper的源码中会有新的体会和领悟!树立目标,坚持去做,不断的提升自己的理解和领悟,才能超越过去的自己!
Angular2的input和output(原先的properties和events)
angular2学习笔记
本文地址:http://blog.csdn.net/sushengmiyan
本文作者:苏生米沿
文章来源:http://blog.ng-book.com/angular-2-component-inputs-and-inputs-formerly-properties-and-events/
angular2的开发迭代笔记快,其中一个重大API变化就是组件(components)现在有input和outputs了。
过去,我们这样定义一个组件:
@Component({ selector: 'my-component',properties: ['product'],events: ['onAdd'] }}
现在不一样了:
@Component({ selector: 'my-component',inputs: ['product'],outputs: ['onAdd'] }}
这个API的改动是有争议的,不过它也是有意义的。
关于这个争议,在git上有激烈的讨论,感兴趣的可以看下:
https://github.com/angular/angular/pull/4435#issuecomment-144789359
Array.ConvertAll 数组相互转化方法
有个需求,把char数组转换为int数组,然后噼里啪啦就弄了这样一堆代码;
public static int[] CharArrToIntArr(char[] charArr)
{
int[] ints = new int[charArr.Length];
for (int i = 0; i < charArr.Length; i++)
{
ints[i] = (int)charArr[i];
}
return ints;
}
后来又有需求,把int数组在转换为char数组,然后上面代码又噼里啪啦弄了一堆,这个时候就发现,
写的这一堆代码是多么的辣鸡,一个类型转换需要那么多代码,如果在遇到string数组转char数组,
char数组再转string数组,这样转换来转换去,一点都不优雅;
后来找到了一个Array.ConvertAll<TInput, TOutput> 方法,完美解决:
这个方法用途:将一种类型的数组转换为另一种类型的数组,比如讲char[] 数组转化为int[] 数组。
类型参数
- TInput: 源数组元素的类型。
- TOutput: 目标数组元素的类型。
- 示例代码:
- 将char 数组转换为int 数组
char[] charArray = new char[] { ''a'', ''b'', ''c'' };
int[] intArray = Array.ConvertAll<char, int>(charArray, value => Convert.ToInt32(value));
对比之后,发现代码简洁了好多,那么效率有什么区别呢?
来对比一波
char[] charArray = new char[] { ''a'', ''b'', ''c'' };
DateTime startDate = DateTime.Now;
for (int i = 0; i < 100; i++)
{
//int[] intArray = Array.ConvertAll<char, int>(charArray, value => Convert.ToInt32(value));
int[] intArray = Test_1.CharArrToIntArr(charArray);
}
DateTime endDate = DateTime.Now;
Console.WriteLine((endDate - startDate).TotalMilliseconds);
运行了十次之后,看下平均值,发现二者差距不是特别大,不过还是推荐 Array.ConvertAll 方法,因为是原生的,简洁明了;
boost :: archive :: binary_oarchive =程序崩溃?
我有一个使用boost::archive::binary_oarchive 。 在执行程序时,当实例化ia >> boost::serialization::make_binary_object(buffer,size)时,程序崩溃。 使用boost::archive::text_oarchive它可以工作…
#include <boost/archive/binary_oarchive.hpp> #include <boost/archive/binary_iarchive.hpp> #include <boost/serialization/string.hpp> #include <boost/serialization/binary_object.hpp> #include <iostream> #include <fstream> using namespace std; void save() { size_t size = 0; std::ifstream infile("any_file.png",std::ios::in | std::ios::binary | std::ios::ate); if (infile.is_open()) { size = infile.tellg(); char *buffer = new char[size]; infile.seekg(0,ios::beg); infile.read(buffer,size); infile.close(); std::ofstream file("archiv.bin"); boost::archive::binary_oarchive oa(file); oa << size; oa << boost::serialization::make_binary_object(buffer,size); file.close(); delete [] buffer; } } void load() { size_t size = 0; std::ifstream file("archiv.bin"); boost::archive::binary_iarchive ia(file); ia >> size; char *buffer = new char[size]; ia >> boost::serialization::make_binary_object(buffer,size); //program crash file.close(); ofstream outfile("any_file_out.png",ios::out | ios::binary); for(size_t i = 0; i < size; i++) { outfile << buffer[i]; } outfile.close(); delete [] buffer; } int main() { save(); load(); return 0; }
先谢谢你!
编辑:这是如何工作的。
... std::ofstream file("archiv.bin",ios_base::binary); ... std::ifstream file("archiv.bin",ios_base::binary); ...
如何在C ++中使用inheritance对类进行序列化
用于将串行端口数据存储在固件中的数据结构
从未知文件中提取序列化的数据
将文件元数据存储在额外的文件中
Linux上的C ++串口。 在串口上可以同时读写吗?
C#JSON对象不会反序列化
在实现video游戏的基本二进制序列化时,可移植性是否需要担心?
在文件描述符上使用fwrite /将文件描述符转换为文件指针
在C ++中跨进程边界发送对象的深层副本
我如何序列化System.Security.AccessControl.FileSecurity?
解决方案呈现本身:)
... std::ofstream file("archiv.bin",ios_base::binary); ...
现在完美的工作!
Cannot set the value of read-only property ''outputFile'' for ApkVariantOutputImpl_Dec
Android Gradle 升级到 3.0 更改输出的 Apk 安装包的名字 报错
Cannot set the value of read-only property ''outputFile'' for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=xiaomiDebug, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.
项目原来的代码
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith(''.apk'')){
def fileName = outputFile.name.replace(".apk",
"-${defaultConfig.versionName}.apk")
output.outputFile = new File(outputFile.parent,fileName)
}
}
}
更改后的
applicationVariants.all { variant ->
variant.outputs.all { output ->
def fileName
if (outputFile != null && outputFile.name.endsWith(''.apk'')) {
fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk")
outputFileName = fileName
}
}
}
关于通过Zoopkeeper-BinaryOutputArchive类学习utf-8的实现和zoo conservation programmes解析的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Angular2的input和output(原先的properties和events)、Array.ConvertAll
本文标签: