在我们日常的开发中使用最多的Java知识点就是Java的IO流和Java集合两大模块,后续的文章我会接着介绍Java集合的知识,本篇博文我主要讲解Java的输入流和输出流。

我们知道任何的编程语言,首先要解决的就是如何与外部介质交换数据,这就包括了如何将数据写到外部介质以及如何读取外部介质的数据;Java的I/O流提供了读写数据的标准方法,Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。

Java的I/O流按读写方式可以分为字节流和字符流两种类型;其实字符流的本质还是字节流,只不过字符流对字节流做了一次封装。需要注意的是:当我们读写二进制文件时(如:图片、视频、音频等),只能使用字节流,否则会操作失败。

按照读写介质的不同,对于I/O流我们还有另一种划分方法,分别是面向显示器、键盘的操作、面向内存的操作、面向磁盘的操作以及面向网络的操作。

输入流、输出流中的输入和输出均是相对于Java程序来说,输入即是向程序输入数据(读),输出即是程序向外部输出数据(写)。

I/O流的相关类如下图所示:

结合我自身开发的经验,我认为按照读写介质来讲解理解会更加直观,所以下面我会按照不同的读写介质来讲解I/O流。

1、面向显示器、键盘的读写操作(标准输入、输出)

面向显示器的写操作和面向键盘的读操作,就是我们常用的System.out和System.in;使用System.out可以向我们的显示器输出信息,使用System.in可以从我们的键盘获取信息,示例代码如下:

/***标准输入输出*/publicclassSystemIOTest{publicstaticvoidmain(String[]args)throwsException{System.out.println("请输入姓名:");Scannerscanner=newScanner(System.in);System.out.println(scanner.nextLine());}}

2、面向磁盘的读写操作

面向磁盘的读写操作,主要就是指对文件的读写操作,它主要包括FileInputStream、FileOutputStream、FileReader、FileWriter,示例代码如下:

/***javaio测试类*/publicclassJavaIOTest{/***字节流读取二进制文件(如图片、音乐文件)*/@TestpublicvoidinputstreamPicTest(){try{InputStreaminputStream=newFileInputStream("e:"+File.separator+"logo.png");OutputStreamoutputStream=newFileOutputStream("e:"+File.separator+"copy.png");byte[]bytes=newbyte[1024];intlen=0;while((len=inputStream.read(bytes))!=-1){outputStream.write(bytes,0,len);}inputStream.close();outputStream.close();}catch(Exceptione){e.printStackTrace();}}/***字节流读取文本*/@TestpublicvoidinputStreamTxt(){try{InputStreaminputStream=newFileInputStream("e:"+File.separator+"sql.txt");OutputStreamoutputStream=newFileOutputStream("e:"+File.separator+"copy.txt");byte[]chars=newbyte[1024];intlen=0;while((len=inputStream.read(chars))!=-1){outputStream.write(chars,0,len);outputStream.flush();}inputStream.close();outputStream.close();}catch(Exceptione){e.printStackTrace();}}/***字符流读取文本*字符流直接读取文本时,中文可能会乱码,所以通过InputStreamReader建字节流转换为字符流*/@TestpublicvoidinputReaderTxt(){try{InputStreamReaderreader=newInputStreamReader(newFileInputStream("e:"+File.separator+"sql.txt"),"GBK");Writerwriter=newFileWriter("e:"+File.separator+"copy.txt");intlen=0;char[]chars=newchar[1024];while((len=reader.read(chars))!=-1){writer.write(chars,0,len);writer.flush();}reader.close();writer.close();}catch(Exceptione){e.printStackTrace();}}/***通过字符串的方式读取文本(可以提高效率)*/@TestpublicvoidstringTxt(){try{InputStreamReaderinputStreamReader=newInputStreamReader(newFileInputStream("e:"+File.separator+"sql.txt"),"GBK");BufferedReaderreader=newBufferedReader(inputStreamReader);Stringstr="";while((str=reader.readLine())!=null){System.out.println("=="+str);}inputStreamReader.close();reader.close();}catch(Exceptione){e.printStackTrace();}}}

3、面向内存的读写操作

面向内存的读写操作,主要用于中间数据的缓存,主要包括:ByteArrayInputStream、ByteArrayOutputStream、ObjecInputStream、ObjectOutputStream,示例代码如下:

/***javaio测试类*/publicclassJavaIOTest{/***对象流(可用于对象的序列化和反序列化)*仅测试使用,Java原生的序列化和反序列化效率较低,建议使用Hession*对象序列化至文件*/@TestpublicvoidtestObjectInputstream(){try{Filefile=newFile("e:"+File.separator+"seri.txt");if(!file.exists()){file.createNewFile();}ObjectOutputStreamoutputStream=newObjectOutputStream(newFileOutputStream("e:"+File.separator+"seri.txt"));SeriEntityseriEntity=newSeriEntity("helloworld");outputStream.writeObject(seriEntity);outputStream.close();outputStream.flush();ObjectInputStreaminputStream=newObjectInputStream(newFileInputStream("e:"+File.separator+"seri.txt"));SeriEntityobj=(SeriEntity)inputStream.readObject();inputStream.close();System.out.println("========"+obj.getName());}catch(Exceptione){e.printStackTrace();}}/***对象流(可用于对象的序列化和反序列化)*对象序列化至内存*/@TestpublicvoidtestObjectInputStreamByte(){try{SeriEntityseriEntity=newSeriEntity("namename");ByteArrayOutputStreambyteArrayOutputStream=newByteArrayOutputStream();ObjectOutputStreamoutputStream=newObjectOutputStream(byteArrayOutputStream);outputStream.writeObject(seriEntity);outputStream.flush();ObjectInputStreaminputStream=newObjectInputStream(newByteArrayInputStream(byteArrayOutputStream.toByteArray()));SeriEntityentity=(SeriEntity)inputStream.readObject();inputStream.close();System.out.println("======"+entity.getName());}catch(Exceptione){e.printStackTrace();}}}

4、面向网络的的操作

面向网络的操作即Java的网络编程,主要包括Socket、ServerSocket,示例代码如下:

/***java网络编程--客户端*/publicclassNetClient{/***服务端IP地址*/privatestaticfinalStringSERVERADDR="127.0.0.1";/***服务端提供的端口号*/privatestaticfinalintSERVERPORT=9090;publicstaticvoidmain(String[]args){Socketsocket=null;try{//和服务端建立连接socket=newSocket(SERVERADDR,SERVERPORT);System.out.println("==========客户端已启动==============");//向服务端发送数据Stringdata="java网络编程实例程序";//获取网络输出流OutputStreamoutputStream=socket.getOutputStream();//向网络输出流写入数据(即向服务端发送数据)outputStream.write(data.getBytes());outputStream.flush();//写关闭,不然会一直阻塞着,服务器会认为客户端还一直在写数据//由于从客户端发送的消息长度是任意的,客户端需要关闭连接以通知服务器消息发送完毕,如果客户端在发送完最后一个字节后//关闭输出流,此时服务端将知道"我已经读到了客户端发送过来的数据的末尾了,即-1",就会读取出数据并关闭服务端的读数据流,在之后就可以//自己(服务端)的输出流了,往客户端写数据了socket.shutdownOutput();//接收服务端数据InputStreaminputStream=socket.getInputStream();byte[]bytes=newbyte[1024];intlen=1;while((len=inputStream.read(bytes))!=-1){System.out.println(newString(bytes,"UTF-8"));}}catch(Exceptione){e.printStackTrace();}finally{try{socket.close();}catch(IOExceptione){e.printStackTrace();}}}}/***java网络编程--服务端*/publicclassNetServer{/***服务端提供的端口*/privatestaticfinalintSERVERPORT=9090;publicstaticvoidmain(String[]args){ServerSocketserverSocket=null;try{serverSocket=newServerSocket(SERVERPORT);System.out.println("===========服务端已启动===========");while(true){//接收客户端请求Socketsocket=serverSocket.accept();//接收客户端发送的信息InputStreaminputStream=socket.getInputStream();byte[]bytes=newbyte[1024];intlen=1;System.out.println("客户端发送消息:");while((len=inputStream.read(bytes))!=-1){System.out.println(newString(bytes,"UTF-8"));}Stringdata="服务端已收到消息";System.out.println(data);OutputStreamoutputStream=socket.getOutputStream();outputStream.write(data.getBytes());outputStream.flush();//写关闭,不然会一直阻塞着,服务器会认为客户端还一直在写数据//由于从客户端发送的消息长度是任意的,客户端需要关闭连接以通知服务器消息发送完毕,如果客户端在发送完最后一个字节后//关闭输出流,此时服务端将知道"我已经读到了客户端发送过来的数据的末尾了,即-1",就会读取出数据并关闭服务端的读数据流,在之后就可以//自己(服务端)的输出流了,往客户端写数据了socket.shutdownOutput();}}catch(Exceptione){e.printStackTrace();}finally{try{serverSocket.close();}catch(IOExceptione){e.printStackTrace();}}}}



由于篇幅有限文章中的代码无法一一列出,如需获取全部的源码信息,可关注微信公众号布衣暖,回复 java基础 获取全部的源码信息