public class Test {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
一般我们学习一门新的语言,都是从她的Hello World开始:
System.out.println("Hello world");
这句代码为什么能输出个"Hello World"到屏幕呢?带着这个问题我们可以进入System类的代码
public final class System {
private System() {
}
public final static InputStream in = null;
public final static PrintStream out = null;
public final static PrintStream err = null;
······
}
看以看出System.out其实是个PrintStream对象。
PrintStream extends FilterOutputStream
FilterOutputStream extends OutputStream
从继承关系中我们可以看出,OutputStream是它们的基类(父类),而OutputStream又是什么?和PrintSteam又是什么关系?为了解答这个,我们就要进入JAVA输出/输入的世界。
我们先来看IO体系的关系:
我们先来看看文件类——File类
File存放在java.io中,在API文档中,对File的描述是An abstract representation of file and directory pathnames(文件和目录路径名的抽象表示)。
File本身并不承担着输入输出的责任,他负责的是管理文件以及目录。
public static void main(String[] args) throws IOException {
//创建个文件,没有指定路径,默认当前路径
File file = new File("HelloWorld.txt");
if (!file.exists())
file.createNewFile(); //创建文件
//下面是将信息传输到文件
FileOutputStream fileOutputStream = new FileOutputStream(file);
byte buffer[] = new byte[512];
//获得键盘输入
System.in.read(buffer);
fileOutputStream.write(buffer);
}
运行代码,程序便在当前路径创建了个“Hello World”的文件,在键盘输入"Hello World"后,就可以就可以文件中看到,文件里面已经产生了“Hello World”。
整个工作流程就是:键盘的信息——>内存——>"Hello World"文件
当然我们也可以指定他的路径:
File path =new File("C:\\");
File file = new File(path,"HelloWorld.txt");
Java的流
说的java的流,我们首先要明白一个东西,就是输入输出,这里的输入输出是相对于内存的,将数据传送到内存,就是输入,从内存传送到其他地方,就是输出。
数据流是一串连续不断的数据的集合,就象水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流。数据写入程序可以是一段、一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流。
在java.io包中有四个基本类:InputStream、OutputStream及Reader、Writer类,它们分别处理字节流和字符流:
输入/输出
字节流
字符流
输入流
Inputstream
Reader
输出流
OutputStream
Writer
在java中,一个字节为8位,一个字符为16位,也就是2个字节,也就是说字符流能传输的数据,字节流也可以传输,而字节流能传输的数据,字节流不一定能传输,但有个问题是,字节流传输效率比字符流慢,所以类似于文本文件,我们应该用字符流的传输方式。
字节流
InputStream :为字节输入流,它本身为一个抽象类,必须依靠其子类实现各种功能,此抽象类是表示字节输入流的所有类的超类。
InputStream类提供了3种重载的read方法.Inputstream类中的常用方法:
(1) public abstract int read( ):读取一个byte的数据,返回值是高位补0的int类型值。若返回值=-1说明没有读取到任何字节读取工作结束。
(2) public int read(byte b[ ]):读取b.length个字节的数据放到b数组中。返回值是读取的字节数。该方法实际上是调用下一个方法实现的
(3) public int read(byte b[ ], int off, int len):从输入流中最多读取len个字节的数据,存放到偏移量为off的b数组中,该方法最后调用read( )。
(4) public int available( ):返回输入流中可以读取的字节数。注意:若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用,
(5) public long skip(long n):忽略输入流中的n个字节,返回值是实际忽略的字节数, 跳过一些字节来读取
(6) public int close( ) :我们在使用完后,必须对我们打开的流进行关闭.
OutputStream:同为抽象类,需要依靠子类实现,提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。
1. public void write(byte b[ ]):将参数b中的字节写到输出流。
2. public void write(byte b[ ], int off, int len) :将参数b的从偏移量off开始的len个字节写到输出流。
3. public abstract void write(int b) :先将int转换为byte类型,把低字节写入到输出流中。
4. public void flush( ) : 将数据缓冲区中数据全部输出,并清空缓冲区。
5. public void close( ) : 关闭输出流并释放与流相关的系统资源。
关于这个flush(),并不是必须用到。
在BufferedOutputStream的API中,close()的描述的第一句话是Flushes this buffered output stream.
在BufferedWriter的API中,close()的描述的第一句话是Closes the stream, flushing it first.
在他们各种的源代码中,我们可以看到,重写的close()方法都已经调用了flush( ),所以说,调用了close(),就可以不用调用flush( )。