第十七章 I/O系统

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;
	}
	
	
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值