Java.io之CharArrayWriter

CharArrayWriter是字符数组输入流,与ByteArrayOutputStream类似,只不过前者是字符后者是字节。

字段

1
2
3
4
//字符数据池
protected char buf[];
//数据池中有效字符数量
protected int count;

构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
//字符数据池的默认大小是32
public CharArrayWriter() {
this(32);
}

//自定义字符数据池大小
public CharArrayWriter(int initialSize) {
if (initialSize < 0) {
throw new IllegalArgumentException("Negative initial size: "
+ initialSize);
}
buf = new char[initialSize];
}

写入方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//向数据池中写入一个int值表示的字符 数据池动态扩容
public void write(int c) {
synchronized (lock) {
int newcount = count + 1;
if (newcount > buf.length) {
buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
}
buf[count] = (char)c;
count = newcount;
}
}

//向数据池中写入c[off] ~ c[off+len-1]的字符 数据池动态扩容
public void write(char c[], int off, int len) {
if ((off < 0) || (off > c.length) || (len < 0) ||
((off + len) > c.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
synchronized (lock) {
int newcount = count + len;
if (newcount > buf.length) {
buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
}
System.arraycopy(c, off, buf, count, len);
count = newcount;
}
}

//向数据池中写入str.subString(off, off+len)的子字符串 数据池动态扩容
public void write(String str, int off, int len) {
synchronized (lock) {
int newcount = count + len;
if (newcount > buf.length) {
buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
}
str.getChars(off, off + len, buf, count);
count = newcount;
}
}

//将当前字符数组输出流中的数据写入字符输出流out中
public void writeTo(Writer out) throws IOException {
synchronized (lock) {
out.write(buf, 0, count);
}
}

append方法

区别于write()在于append()返回CharArrayWriter对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//等同于:write(csq.toString, 0, csq.length)
public CharArrayWriter append(CharSequence csq) {
String s = (csq == null ? "null" : csq.toString());
write(s, 0, s.length());
return this;
}

//等同于:write(csq.toString, start, end)
public CharArrayWriter append(CharSequence csq, int start, int end) {
String s = (csq == null ? "null" : csq).subSequence(start, end).toString();
write(s, 0, s.length());
return this;
}

////等同于:write(c)
public CharArrayWriter append(char c) {
write(c);
return this;
}

辅助方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//不用申请数据池内存资源 直接清空数据池
public void reset() {
count = 0;
}

//数据池转字符数组
public char toCharArray()[] {
synchronized (lock) {
return Arrays.copyOf(buf, count);
}
}

//数据池大小
public int size() {
return count;
}

//数据池转String
public String toString() {
synchronized (lock) {
return new String(buf, 0, count);
}
}

//无副作用
public void flush() { }

//无副作用
//关闭CharArayWriter之后仍可操作数据池
public void close() { }

讨论

CharArayWriter源码比较简单 此处稍微讨论一下代码中几个细节。

几个提到的方法

1
2
3
4
5
6
//会创建新数组 该方法的底层还是调用了System.arrayCopyOf()方法
dataType[] Arrays.copyOf(dataType[] srcArray,int length);

void System.arraycopy(dataType[] srcArray,int srcIndex,int destArray,int destIndex,int length)

void String.getChars(int strBegin, int strEnd, char[] dst, int dstBegin)

write(char[], int, int)的参数校验

这样严谨的参数校验值得学习 可以在日后的代码中用起来

1
2
3
4
if ((off < 0) || (off > c.length) || (len < 0) ||
((off + len) > c.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
}
  • off < 0: 起始位置必须大于等于0
  • off > c.length: 起始位置必须小于数组长度
  • len: 读取的数据数量必须 >= 0
  • off + len) > c.length: 读取的最后一个数据位置必须不能超过数组长度
  • off + len) < 0: off与len相加不应溢出int
Donate here.