黑马程序员——Java的IO流学习

Java I/O 流与字符文件操作详解

------- android培训java培训、期待与您交流! ----------

Java中的io流主要是用于对设备上的数据进行处理——读写操作。分类:输入流(读)和输出流(写),按处理的数据不同分为字节流和字符流。字节流是处理字节数据的流对象,是一种通用的数据处理方式,因为设备上的任何数据都是以字节的形式存在的。字符流是以字节流为基础然后加上编码表通过解析得到正确的字符数据,由于各国语言文字的差异所以在处理字符数据的时候,需要加入特定的编码表并经过解析才能得到正确的字符,所以,该对象普遍应用于文本数据的操作。

流的体系注意设计四个类——抽象类,对应于读写操作:字节流——InputStream、OutputStream,字符流——Reader、Writer。对处理一些文本数据的操作,通常使用字符流对象,由于Reader和Writer是抽象类,只能通过他们的子类来实例化对象,通过对子类对象的操作进行读取和写入数据的功能,先看FileWriter的用法,通过其构造函数创建一个文件对象(如果文件不存在),然后,调用该对象的write方法向文件中写入字符数据,最后,一定要关闭文件对象,不然无法将数据写入到文件——这是因为在调用write方法时,只是把字符数据写入到了一个缓冲区,而没有真正将缓冲区数据写入到文件,这是还要调用flush方法来刷新缓冲区到文件才能写入,close方法中有flush的操作,故可以将数据写入文件。

操作数据的一般步骤:因为io流的操作都可能抛异常(比如文件创建失败、写入或读取不到等),而这个异常通常是需要自己来处理,故在进行文件处理时要利用try组合来处理可能的异常。

import java.util.*;
import java.io.*;

class CharWriterDemo 
{
	public static void main(String[] args) 
	{
		//创建一个全局的对象,保证每个模块都能访问该引用
		FileWriter fileWriter=null;
		try
		{
			//创建一个文件对象,注意可能抛异常,若抛出异常文件对象就没有创建成功,fileWriter是null,
			//finally模块需要进行判断,不为空才执行关闭资源的操作
			fileWriter=new FileWriter("charWiter.txt",true);
			//写入字符数据
			//通过键盘输入数据,然后将数据写入到文件
			Scanner sc=new Scanner(System.in);
			
			while(true)
			{
				String str=sc.nextLine();
				if("over".equals(str))
					fileWriter.close();
				fileWriter.write(str);
			}
			//fileWriter.close();
		}
		catch (IOException e)
		{
			e.getStackTrace();
		}
		finally
		{
			try
			{
				if(fileWriter!=null)
					fileWriter.close();
			}
			catch (IOException e)
			{
				e.getStackTrace();
			}
		}
	}
}

注意,write方法有不同的重载形式,可以写入单个字符、基本数据类型、字符数组还可以写入字符串,实例中我用的是写入字符串的形式。


FileReader读取操作:整个过程同写入操作类似,整个过程也是可能会抛异常,所以,要进行异常的try处理,在读取文件内容的时候有两种方式:一个是一次读取一个字符,还有就是一次读取一个缓冲区(字符数组)。主要利用read方法,两种方式其返回值代表不同的意义:读取单字符的时候,返回int数据代表字符,若读到结尾则返回-1,因此可以通过其返回值来不断取出文件中的字符数据;自定义缓冲区,读取字符数组时,返回int型数据表示当前数组中读取的字符数量,没有数据读入时返回-1。

import java.io.*;
class CharReaderDemo 
{
	public static void main(String[] args) 
	{
		FileReader fileReader=null;
		try
		{
			fileReader=new FileReader("charWiter.txt");
			//第一种读取文件数据方式,单字符方式
			/*int ch=0;
			StringBuilder sb=new StringBuilder();
			while((ch=fileReader.read())!=-1)
			{
				sb.append((char)ch);
			}

			fileReader.close();
			System.out.println("方式一读取结果:"+sb.toString());*/

			//第二种方式,自定义一个缓冲区
			StringBuilder sb1=new StringBuilder();
			char[] buf=new char[1024];
			int charNum=0;//用作记录读入到缓冲区的字符数
			while((charNum=fileReader.read(buf))!=-1)
			{
				sb1.append(new String(buf,0,charNum));
			}
			fileReader.close();
			System.out.println("方式二读取结果:"+sb1.toString());
		}
		catch (IOException e)
		{
			e.getStackTrace();
		}
		finally
		{
			try
			{
				if(fileReader!=null)
					fileReader.close();
			}
			catch (IOException e)
			{
				e.getStackTrace();
			}
		}
	}
}

三、下面两个功能函数分别用字符流对象创建字符文件和利用字节流文件进行数据文件的拷贝,通过这两个函数演示字符流对象和字节流对象的用法。

import java.util.*;
import java.io.*;
class BufferedDemo 
{
	public static void main(String[] args) 
	{
		//System.out.println("Hello World!");
		//createTxtFile();
		long start=System.currentTimeMillis();
		copyFile("D:\\01_093353.264","D:\\3.264");
		long end=System.currentTimeMillis();
		System.out.println("用时:"+(end-start)+"毫秒");
		
	}
	public static void createTxtFile()
	{
		FileWriter fw=null;
		BufferedWriter buf=null;
		Scanner sc=null;
		try
		{
			fw=new FileWriter("BufWriter.txt");
			//通过一个装饰类将fw作为被装饰对象传入,扩展写入功能。
			//BufferedWriter是一个装饰类(装饰设计模式)
			buf=new BufferedWriter(fw);

			//通过键盘输入需要写入的内容
			//方法一
			//br=new BufferedReader(new InputStreamReader(System.in));
			sc=new Scanner(System.in);
			String str="";
			//可由键盘输入多行文本数据
			while((str=sc.nextLine())!=null)
			{
				//over表示结束,文件写入完成
				if("over".equals(str))
				{
					return;
				}
				//写入当前输入行字符串
				buf.write(str);
				//添加新行
				buf.newLine();
				//将写入字符串从缓冲区取出,写入文件,不加此语句无法写入文件
				buf.flush();
			}
			buf.close();
			
		}
		catch (IOException e)
		{
			e.getStackTrace();
		}
		finally
		{
			try
			{
				if(fw!=null)
					fw.close();
			}
			catch (IOException e)
			{
				//e.getStackTrace();
				System.out.println(e.getMessage());
			}
			try
			{
				if(buf!=null)
					buf.close();
			}
			catch (IOException e)
			{
				//e.getStackTrace();
				System.out.println(e.getMessage());
			}
		}
	}
	//文件复制
	public static void copyFile(String src,String des)
	{
		//定义两个缓冲读取和写入的流对象,是两个修饰类,可以通过传入OutputStream和InputStream对象引用,实现读取和写入增强功能。
		BufferedInputStream bufR=null;
		BufferedOutputStream bufW=null;
		try
		{
			//将FileInputStream和FileOutputStream对象作为参数传给bufR和bufW
			bufR=new BufferedInputStream(new FileInputStream(src));
			bufW=new BufferedOutputStream(new FileOutputStream(des));

			//申请一块缓冲区,用作保存读取的字节流数据
			byte[] buf=new byte[1024];
			int num=0;
			//从源数据不断读取流信息
			while((num=bufR.read(buf))!=-1)
			{
				//写入数据
				bufW.write(buf,0,num);
				//刷新缓冲区,从缓冲区取出数据写入文件
				bufW.flush();
			}
			//关闭资源
			bufR.close();
			bufW.close();
		}
		catch (IOException e)
		{
			//e.getStackTrace();
			System.out.println(e.getMessage());
		}
		finally
		{
			try
			{
				if(bufR!=null)
					bufR.close();
			}
			catch (IOException e)
			{
				//e.getStackTrace();
				System.out.println(e.getMessage());
			}
			try
			{
				if(bufW!=null)
					bufW.close();
			}
			catch (IOException e)
			{
				//e.getStackTrace();
				System.out.println(e.getMessage());
			}
		}
	}
}



### TCP传输原理与实现 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节的传输层协议。其核心原理是通过建立端到端的连接,确保数据在不可靠的网络中能够可靠地传输。TCP 使用确认机制、量控制、拥塞控制等机制来保障数据的完整性和有序性。 在 Java 中,TCP 通信可以通过 `Socket` 和 `ServerSocket` 类实现。客户端使用 `Socket` 连接到服务器,服务器端使用 `ServerSocket` 监听连接请求。通信过程中,数据通过输入和输出进行传输。 #### 客户端实现 客户端的主要任务是与服务器建立连接,并通过输出向服务器发送数据,同时可以通过输入接收服务器的响应。例如: ```java Socket s = new Socket(InetAddress.getLocalHost(), 10004); OutputStream out = s.getOutputStream(); out.write("Hello TCPClient".getBytes()); InputStream is = s.getInputStream(); byte[] buffer = new byte[1024]; int len = is.read(buffer); System.out.println(new String(buffer, 0, len)); s.close(); ``` 该代码实现了客户端与服务器的连接,并发送了一条文本消息,同时接收服务器的响应[^1]。 #### 服务端实现 服务端通过 `ServerSocket` 监听指定端口,等待客户端连接。一旦连接建立,服务端通过输入接收客户端发送的数据,并通过输出向客户端发送响应。例如: ```java ServerSocket ss = new ServerSocket(10012); Socket s = ss.accept(); InputStream in = s.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println(new String(buffer, 0, len)); PrintWriter out = new PrintWriter(s.getOutputStream(), true); out.println("<font color='red' size=7>客户端s你好</font>"); s.close(); ss.close(); ``` 该代码展示了如何在服务端接收客户端发送的数据,并向客户端发送 HTML 格式的响应[^3]。 #### TCP连接的建立与释放 TCP 连接的建立采用三次握手(Three-way Handshake): 1. 客户端发送 SYN(同步)报文给服务器,表示请求建立连接。 2. 服务器收到 SYN 报文后,发送 SYN-ACK(同步-确认)报文作为响应。 3. 客户端收到 SYN-ACK 后,发送 ACK(确认)报文,连接建立。 连接的释放采用四次挥手(Four-way Handshake): 1. 客户端发送 FIN(结束)报文,表示数据发送完成。 2. 服务器发送 ACK 报文,确认收到 FIN。 3. 服务器发送 FIN 报文,表示数据发送完成。 4. 客户端发送 ACK 报文,连接关闭。 #### TCP的可靠性机制 TCP 通过以下机制确保数据的可靠传输: - **确认机制**:接收方收到数据后,向发送方发送确认信息。 - **重传机制**:如果发送方未收到确认信息,则重传数据。 - **量控制**:通过滑动窗口机制,控制发送速率,避免接收方缓冲区溢出。 - **拥塞控制**:通过慢启动、拥塞避免等算法,防止网络拥塞。 #### TCP的编程模型 TCP 编程模型通常包括以下几个步骤: 1. **创建 Socket**:客户端创建 `Socket` 对象,连接服务器;服务端创建 `ServerSocket` 对象,监听端口。 2. **获取对象**:获取 `Socket` 的输入和输出,用于数据传输。 3. **数据读写**:通过输入读取数据,通过输出写入数据。 4. **关闭连接**:通信结束后,关闭 `Socket` 和对象。 ### 示例代码:完整的 TCP 通信 以下是一个完整的 TCP 通信示例,包含客户端和服务端的代码。 #### 客户端代码 ```java import java.io.*; import java.net.*; public class TcpClient { public static void main(String[] args) { try { Socket socket = new Socket("localhost", 8888); OutputStream out = socket.getOutputStream(); out.write("Hello Server!".getBytes()); InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println("Server response: " + new String(buffer, 0, len)); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` #### 服务端代码 ```java import java.io.*; import java.net.*; public class TcpServer { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Server is listening on port 8888..."); Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = in.read(buffer); System.out.println("Client message: " + new String(buffer, 0, len)); OutputStream out = socket.getOutputStream(); out.write("Hello Client!".getBytes()); socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值