window 默认的编码是gbk。可以使用chcp命令查看,结果为936.
抽象类inputstream (outputstream),面向字节。
这两个方法是针对字节的输入输出流,相对于reader、writer是针对字符的输入输出。从以下数据源读取数据
* 字节数组
* String对象
* 文件
* 管道
主要方法:
* read(),读取输入流的下一个字节。
(在outputstream中对应的是write())。用于读取一个字节。
基本方法很少使用,而是通过叠合多个对象来提供所期待的功能,这种成为装饰器模式。装饰器模式相比继承更好。
* available() ,还有多少字节可以读入,InputStream中直接return 0;
* read(byte[] b) 试图读入多个字节,存入字节数组b,返回实际读入的字节数
* public long skip(long n)throws IOException 跳过n个字节,返回实际跳过的字节数。
* void mark(int readlimit) ,在流的当前位置做个标记,参数readLimit指定这个标记的“有效期“,如果从标记处开始往后,已经获取或者跳过了readLimit个字节,那么这个标记失效,不允许再重新回到这个位置。
* void reset() ,重定位到最近的标记,回到之前mark的位置。如果没有mark过或者标记失效了,抛出异常。
代码实例
InputStream is = null;
try {
//test.txt 内容。123456789
is = new BufferedInputStream(new FileInputStream("C:\\Users\\jiaoz\\Documents\\test.txt"));
//BufferedInputStream 是否支持mark(n)
System.out.println(is.markSupported());
//读两个字节
System.out.println((char)is.read());
System.out.println((char)is.read());
is.mark(4);
is.skip(2);
is.reset();
System.out.println((char)is.read());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
is.close();
}
}
Reader(Writer),面向字符。
与inputStream面向字节不同。
主要方法:
* read() Reads a single character.
* read(char[] cbuf)
子类:
* InputStreamReader 适配器类,new InputStreamReader(new FileInputStream(file));参数为InputStream.可以读入一个字符。
* BufferedReader,构造方法 BufferedReader(Reader in)。readline()方法。
输入输出重定向
// 此刻直接输出到屏幕
System.out.println("hello");
File file = new File("d:" + File.separator + "hello.txt");
try{
System.setOut(new PrintStream(new FileOutputStream(file)));
}catch(FileNotFoundException e){
e.printStackTrace();
}
System.out.println("这些内容在文件中才能看到哦!");
}
合并流 SequenceInputStream
File file1 = new File("d:" + File.separator + "hello1.txt");
File file2 = new File("d:" + File.separator + "hello2.txt");
File file3 = new File("d:" + File.separator + "hello.txt");
InputStream input1 = new FileInputStream(file1);
InputStream input2 = new FileInputStream(file2);
OutputStream output = new FileOutputStream(file3);
// 合并流
SequenceInputStream sis = new SequenceInputStream(input1, input2);
int temp = 0;
while((temp = sis.read()) != -1){
output.write(temp);
}
input1.close();
input2.close();
output.close();
sis.close();
文件压缩 ZipOutputStream类
30M的文件压缩完5M,耗时半分钟,非常慢。跟字节流有关。实例代码:
``` java
File file = new File("C:\\Users\\credit100\\Videos\\30KContainGuanggao.sql");
File zipFile = new File("C:\\Users\\credit100\\Videos\\30KContainGuanggao.zip");
System.out.println(file.getName());
InputStream input = new FileInputStream(file);
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
zipOut.putNextEntry(new ZipEntry(file.getName()));
// 设置注释
zipOut.setComment("hello");
int temp = 0;
while((temp = input.read()) != -1){
zipOut.write(temp);
}
input.close();
zipOut.close();
```
PushBackInputStream回退流
unread方法,把已经读到的字节放回去,下次read的时候,可以再一次读到。
String str = "hello,rollenholt";
PushbackInputStream push = null;
ByteArrayInputStream bat = null;
bat = new ByteArrayInputStream(str.getBytes());
push = new PushbackInputStream(bat);
int temp = 0;
while ((temp = push.read()) != -1) {
if (temp == ',') {
push.unread(temp);
temp = push.read();
System.out.print("(回退" + (char) temp + ") ");
} else {
System.out.print((char) temp);
}
}
ObjectOutputStream 写入对象writeObject(new Object());readObject();
File file = new File("d:" + File.separator + "hello.txt");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
file));
//把二进制文件写入到hello.txt;
oos.writeObject(new Person("rollen", 20));
RandomAccessFile 独立的IO类
seek(int n),前进那个字节。
管道流
用于多线程任务之间的通信。
nio
用nio读写示例:
// Write a file:
FileChannel fc =new FileOutputStream("C:\\Users\\jiaoz\\Documents\\MyCode\\api\\test\\data.txt").getChannel();
fc.write(ByteBuffer.wrap("Some text ".getBytes()));
fc.close();
// Add to the end of the file:
fc =new RandomAccessFile("C:\\Users\\jiaoz\\Documents\\MyCode\\api\\test\\data.txt", "rw").getChannel();
fc.position(fc.size()); // Move to the end
fc.write(ByteBuffer.wrap("Some more".getBytes()));
fc.close();
// Read the file:
fc = new FileInputStream("C:\\Users\\jiaoz\\Documents\\MyCode\\api\\test\\data.txt").getChannel();
ByteBuffer buff = ByteBuffer.allocate(BSIZE);
fc.read(buff);
buff.flip();
while (buff.hasRemaining()){
System.out.println();
System.out.print((char) buff.get());}
}
FileChannel 类
Java NIO FileChannel类是NIO用于替代使用标准Java IO API读取文件的方法。getChannel()方法获取fileChannel.
java io和nio中做文件复制的代码对比。
- java io
BufferedInputStream br=new BufferedInputStream(new FileInputStream(old));
BufferedOutputStream bw=new BufferedOutputStream(new FileOutputStream(newCopy));
byte[] bs=new byte[100];
int n;
while((n=br.read(bs))!=-1)
bw.write(bs,0,n);
*java nio
FileChannel oldfc=new FileInputStream(old).getChannel();
FileChannel newfc=new FileOutputStream(newCopy).getChannel();
oldfc.transferTo(0,oldfc.size(),newfc);
nio要比普通的io快很多,普通io的速度跟byte[]数组缓冲器大小有关系。
Buffer缓冲器的细节
buffer有四个重要的指标变量,分别为:
- mark ,使用mark()方法标记当前postition为mark,reset()方法把position设置为mark
- position,初始0、put,get方法会改变其值,get(int n)不会改变值。
- limit,和capacity一直,初始执行最后。
- capacity 重要的方法:
- capacity() 返回容量
- clear() position设为0, limit设为容量,可以调用此方法覆盖buffer
- hasRemaining() 若position和limit中间有值,返回true
代码示例:
public class UsingBuffers {
private static void symmetricScramble(CharBuffer buffer){
while(buffer.hasRemaining()) {
buffer.mark();
char c1 = buffer.get();
char c2 = buffer.get();
buffer.reset();
buffer.put(c2).put(c1);
}
}
public static void main(String[] args) {
char[] data = "UsingBuffers".toCharArray();
ByteBuffer bb = ByteBuffer.allocate(data.length * 2);
CharBuffer cb = bb.asCharBuffer();
cb.put(data);
print(cb.rewind());
symmetricScramble(cb);
print(cb.rewind());
symmetricScramble(cb);
print(cb.rewind());
}
} /* Output:
UsingBuffers
sUniBgfuefsr
UsingBuffers
buffer中的flip()和rewind()的区别
flip()做两件事儿:
- 它将 limit 设置为当前 position。
- 它将 position 设置为 0。
rewind()ONLY 做一件事儿:
- 它将 position 设置为 0。
内存映射文件
把文件当做内存buffer来操作。使用这种方式,读写性能显著提升。
public class LargeMappedFiles {
static int length = 0x8FFFFFF; // 128 MB
public static void main(String[] args) throws Exception {
MappedByteBuffer out =
new RandomAccessFile("test.dat", "rw").getChannel()
.map(FileChannel.MapMode.READ_WRITE, 0, length);
for(int i = 0; i < length; i++)
out.put((byte)’x’);
print("Finished writing");
for(int i = length/2; i < length/2 + 6; i++)
printnb((char)out.get(i));
}
}
文件加锁
java文件加锁直接映射到本地操作系统的加锁工具,所以对于其他java虚拟机或者其他非java进程,均可见。