java中为了保证通用性,在没有明确数据源的情况下也可以编程,进行读写数据操作,而设计的一个特殊的流模型。
里面就是采用了围绕抽象类来编写程序,从而避免了具体的实现和具体的数据源处理。
流:是具有方向和流质的,在java中的数据流一样如此。方向是针对程序来说的。比如输入(就是从外面输入到程序中),输出就是(从程序中输出到外面)。
流的使用必须遵守3步操作:
1.建立流
2.使用流
3.关闭流
一、字节流
字节流的通用性最高,可以传输任何数据类型。比如图片,视频和音频。适用于所有非纯文本和纯文本数据。
字节流的传输最小单位是字节。有:
InputStream和OutputStream这2个抽象父类。是所有输入输出字节流的父类。
常用的方法有read(),write()分别是读写一个字节。每次只读写一个字节,速度太慢
read(byte[] b),write(byte[] b , begin , length)读写字节数组。
第二个方法常用,速度较快。
他们的常用子类有:
1.低级字节流
操作文件的流: FileInputStream,FileOutputStream,File(InputStream/OutputStream)
内存缓存区中的字节数组操作流:ByteArray(……)
2.高级字节流
高级流不能直接访问数据源,必须通过低级流或者其他高级流来 转接
缓冲流:Buffered(……)具有缓冲区的流。默认2k
数据流:Data(……) 可以直接读取与平台无关的java标准基本数据类型及String对象。
打印输出流:PrintSystem,允许基本数据类型直接输出到字符串流中,自动使用本地编码,而且具有自动刷新功能。
对象流:Object(……) 对象的输入输出,可以直接读写对象。
合并流:SequenceInputStream 可以实现2个文件的同时操作,下面2个低级流,第一个流结束时转到另一个流。
二、字符流
字符流的最小操作单位是字符,可以快速的读写纯文本的数据。支持中文
1.低级字符流
文件的:File(Reader/Writer),直接读取文件
内存缓冲区中字符数组:CharArray(Reader/Writer),
内存中的字符串对象:String(Reader/Writer),
2.高级字符流
缓冲流:Buffered(Reader/Writer),
转换流:InputStreamReader,OutputStreamWriter,分别将字节输入流转换为字符输入流 及 将字符输出流转换为字节输出流。
打印输出流:PrintWriter,将基本数据类型输出到字符串流中。,带有自动刷新功能。
三、文件类
当对文件进行操作时,需要一个文件对象。
new File("路径\文件名");通过文件对象可以对文件本身的属性进行访问和操作。(不是内容,内容需通过流)
文件对象也可以是目录
通过mkdir()方法可以创建目录,通过createNewFile()方法可以创建文件。如果之前不存在该文件时。
三、对象的序列化,及反序列化
实现Serializable接口就能对类进行序列化。
不需要实现其他的东西。
该类中除静态static属性和用transient修饰的属性外(这些属性将不参与序列化,值不能通过对象流来传输及保存),其他所有的非基本数据类型属性必须也实现Serializable接口才能使用对象流。
列子:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class ServerThread extends Thread {
private static String day;
private static String savepath;
private static int buffSize;
Socket socket;
private MyFrame father;
public ServerThread(){
}
public ServerThread(Socket socket ,MyFrame father){
this.socket = socket;
this.father =father;
}
@Override
public void run() {
// TODO Auto-generated method stub
/*synchronized(father.getMessageArea())*/{
BufferedOutputStream bos = null;
BufferedInputStream bis = null;
byte[] b = new byte[ServerThread.buffSize];
int length = 0;
try {
System.out.println("接收线程"+Thread.currentThread().getName()+":启动");
//读取文件消息的标志位
int first = this.socket.getInputStream().read();
//接收文件,读取的第一个字节是0
if( first == 0){
byte[] filename = new byte[1024];
int len = 0 ;
int by = 0;
//读文件名,
while((by = this.socket.getInputStream().read()) != 0){
filename[len] = (byte) by;
len++;
}
//重新构造出文件名
File file = new File(this.savepath+File.separator+new String(filename,0,len,"utf-8"));
bos = new BufferedOutputStream(new FileOutputStream(file));
bis = new BufferedInputStream(this.socket.getInputStream());
System.out.println("开始接受文件");
this.father.getMessageArea().append(file.getName()+":接收中……"+"\n");
while((length = bis.read(b)) != -1 ){
System.out.println("接收的数据:"+new String(b,0,length));
bos.write(b, 0, length);
bos.flush();
}
this.father.getMessageArea().append(file.getName()+":接收完成!"+"\n");
System.out.println("文件接收OK");
}else if(first == 1){
//接收消息,消息的标志位为1,需同步消息显示面板
synchronized(father.getMessageArea()){
bis = new BufferedInputStream(this.socket.getInputStream());
StringBuffer sb = new StringBuffer();
String message = null;
while((length =bis.read(b)) != -1){
sb.append(new String(b,0,length,"utf-8"));
}
System.out.println("接收到:"+sb.toString());
String[] ms = sb.toString().split("&",3);
if(!ms[1].contains(this.day)){
this.father.getMessageArea().append(ms[0]+" "+ms[1]+"\n"+ms[2]+"\n");
}else{
this.father.getMessageArea().append(ms[0]+" "+ms[1].substring(10)+"\n"+ms[2]+"\n");
}
}
}
System.out.println("接收线程"+Thread.currentThread().getName()+":结束");
//设置光标到文字的末尾
father.getMessageArea().setCaretPosition(father.getMessageArea().getText().length());
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
this.socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(bis != null){
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(bos != null){
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public static String getDay() {
return day;
}
public static void setDay(String day) {
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
ServerThread.day = sdf.format(now);
}
public static String getSavepath() {
return savepath;
}
public static void setSavepath(String savepath) {
ServerThread.savepath = savepath;
}
public static int getBuffSize() {
return buffSize;
}
public static void setBuffSize(int buffSize) {
ServerThread.buffSize = buffSize;
}
}