Java教程

java文件读写

本文主要是介绍java文件读写,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1、File类

文件和文件夹的基本操作
public class TestFile {	
	public static void main(String[] args) throws IOException {
		File file = new File("d:/a");//文件对象	
		//String[] list = file.list();
		//File[] listFiles = file.listFiles();
		String[] list = file.list(new FilenameFilter() {
			public boolean accept(File dir, String name) {				
				return name.contains("a");
			}
		});		
		System.out.println(Arrays.toString(list));
		//file.createNewFile();		
		//System.out.println(file.exists());//判断是否存在
		//System.out.println(file.canRead());
		//System.out.println(file.canWrite());
		//System.out.println(file.delete());
		//System.out.println(file.getAbsolutePath());
		//System.out.println(file.getName());
		//String fileName = file.getName();
		//System.out.println(fileName.substring(fileName.lastIndexOf(".")+1));
//	    String parent = file.getParent();
//	    System.out.println(parent);
		//long freeSpace = file.getFreeSpace();
		//System.out.println(freeSpace);
	    //System.out.println(file.length());
		//System.out.println(file.getPath());
		//System.out.println(file.isFile());
		//file.mkdirs();
		//System.out.println(file.isDirectory());
	}

}

2、流

java中有四大家族的流,他们都是抽象类:

java.io.InputStream 字节输入流

java.io.OutputStream 字节输出流

java.io.Reader 字符输入流

java.io.Writer 字符输出流

对于文件有这些流常用:

java.io.FileInputStream

java.io.FIleOUtStream

java.io.FileReader

java.io.FileWriter

对象有关的流:

java.io.ObjectInputStream

java.io.ObjectOutputStream

转换流:

OutputStreamWriter

InputStreamReader

2.1 字节流

文件的读和写:

public static void main(String[] args) throws Exception{
		//创建流---指定文件位置
		InputStream is = new FileInputStream("d:/a.txt");
		OutputStream os  = new FileOutputStream("d:/b.txt",true);//已经创建了b.txt
		//调用流的方法去读和写	
		//一个字节一个字节读
//		int data;
//		while((data= is.read())!=-1) {
//			System.out.println((char)data);			
//		}
		//一次读多个字节
		byte[] data = new byte[4];//缓存数组--8*1024
		int length;
		while((length = is.read(data))!=-1) {
			//输出到控制台
			System.out.println(new String(data,0,length));
			os.write(data, 0, length);
		}
		os.write(10);//换行
		//关闭资源
		is.close();
		os.close();
		System.out.println("over");
	}

//找一张图片或者音乐,用字节流操作来复制一下这个图片或音乐
public class TestCopyPic {
	
	public static void main(String[] args) {
		InputStream is= null;
		OutputStream os = null;
		try {
			is = new FileInputStream("d:/th.jpg");			
			os = new FileOutputStream("d:/a/th.jpg",true);
			byte[] buf = new byte[8*1024];
			int length=-1;
			while((length=is.read(buf))!=-1) {
				os.write(buf, 0, length);
			}
		} catch (FileNotFoundException e) {			
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//先开的后关
			try {
				os.close();
				is.close();
			} catch (IOException e) {				
				e.printStackTrace();
			}			
		}		
		
	}

}

2.2、字符流

FileWriter和FileReader中的操作方式和FileInputStream以及FileOutStream相似

2.3、缓冲流

FileReader fileReader = new FileReader("G:/b/b.text");
BufferedReader bufferedReader = new BufferedReader(fileReader);
String s2 = null;
while((s2 = bufferedReader.readLine()) != null){
      System.out.println(s2);
}
bufferedReader.close();

FileWriter fileWriter = new FileWriter("G:/b/b.text");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.newLine();
bufferedWriter.write(123);
bufferedWriter.flush();
bufferedWriter.close();

2.4、序列化流(对象流)

//反序列化流--将序列化过程中所生产的二级制串转化成数据结构或对象
public class ObjectInputStream
    extends InputStream implements ObjectInput, ObjectStreamConstants{}
//序列化流--将数据结构或对象转换成二进制串
public class ObjectOutputStream
    extends OutputStream implements ObjectOutput, ObjectStreamConstants{}
//Serializable接口,当一个类的实例要被对象流读写时,要求必须实现serializable接口

3、socket

服务端:

ServerSocket server = new ServerSocket(6666);
		//启动监听
Socket socket = server.accept();	//一直没有接收到客户端信号就一直阻塞
System.out.println(socket.getInetAddress().getHostAddress()+"连接了服务器");

客户端:

Socket socket = new Socket("10.7.163.102", 6666);

交互客户端:

package com.qf.cdjava2201.day24.chat;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server {
	//接收消息,并且转发消息给所有的客户端--集合,也可以使用线程池
    List<ThreadSocket> clients = new ArrayList<Server.ThreadSocket>();
	public void start() {
		try {
			ServerSocket server = new ServerSocket(8888);			
			while(true) {
				Socket socket = server.accept(); //接收客户端连接
		System.out.println(socket.getInetAddress().getHostAddress()+"连接了服务器");
				//保存这个客户端
			   ThreadSocket client = new ThreadSocket(socket);
			   clients.add(client);			   
			   new Thread(client).start();
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		new Server().start();
	}
	
	public class ThreadSocket implements Runnable{
		Socket socket;
		String name;
		public ThreadSocket(Socket socket) {
			this.socket = socket;
		}
		
		//处理每个客户端的聊天信息
		public void run() {
			//接收一个名字
			try {
                //从socket中获取输入流并建立缓冲区进行读取
				BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			    name = br.readLine();
			    //把名字广播给所有的客户端
			    String msg = "欢迎"+name+"进入聊天室";	
			    sendMsg(msg);
			    while(true) {
			    	//接收消息并转发
			    	BufferedReader br1 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				    String info = br1.readLine();
			    	sendMsg(name+"["+socket.getInetAddress().getHostAddress()+"]:"+info);
			    	System.out.println(name+"["+socket.getInetAddress().getHostAddress()+"]:"+info);
			    	if(info.equals("88")) {
			    		System.out.println(name+"退出了聊天室");
			    		socket.close();
			    		clients.remove(this);
			    		break;
			    	}
			    }			    
			} catch (IOException e) {	
				e.printStackTrace();
			}
		}
		//广播所有信息的方法
		private void sendMsg(String msg) {
			for (ThreadSocket client : clients) {
				try {
					BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.socket.getOutputStream()));
				    bw.write(msg);
				    bw.newLine();
				    bw.flush();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
}
    
   客户端
       
       
       package com.qf.cdjava2201.day24.chat;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Client {
	static boolean flag = true;
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);		
		//建立连接
		try {
			Socket socket = new Socket("127.0.0.1",8888);
			//接收消息--启动一个线程来一直接收消息,客户端不关闭,便一直接收
			new Thread(new Runnable() {
				public void run() {
					while(flag) {
						BufferedReader br=null;
						try {
							br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
							String info="";
							info = br.readLine();
							System.out.println(info);
						} catch (IOException e1) {
							//输入88这里有个异常
						}		    	
					}
				}
			}).start();
			
			//输入昵称发给服务器		
			System.out.println("请输入您的昵称:");
			String name = input.next();
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		    bw.write(name);
		    bw.newLine();
		    bw.flush();			
			
			//发送消息
			while(true) {
				System.out.println("请发送消息:");
				String msg = input.next();
				BufferedWriter bw1 = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			    bw1.write(msg);
			    bw1.newLine();
			    bw1.flush();			    
			    if(msg.equals("88")) {
     //最后关闭流的方式还可以用socket.shutdownOutput()。相比于socket.close(),这个方法是在服务端收到消息后,还能再发消息给客户端,然后再关闭Socket。
		    		socket.close();
		    		flag = false;
		    		break;
		    	}
			}
			
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
//这里设计的通知服务端已发送完命令的方式是设定“88”,但在真实的使用中,肯定是麻烦的,比如不能单独输入88了。
//这里推荐使用“指定长度”的方法。
转载于---博客园,作者:已往之不谏。
 如果你了解一点class文件的结构(后续会写,敬请期待),那么你就会佩服这么设计方式,也就是说我们可以在此找灵感,就是我们可以先指定后续命令的长度,然后读取指定长度的内容做为客户端发送的消息。

  现在首要的问题就是用几个字节指定长度呢,我们可以算一算:

1个字节:最大256,表示256B
2个字节:最大65536,表示64K
3个字节:最大16777216,表示16M
4个字节:最大4294967296,表示4G
依次类推
  这个时候是不是很纠结,最大的当然是最保险的,但是真的有必要选择最大的吗,其实如果你稍微了解一点UTF-8的编码方式(字符编码后续会写,敬请期待),那么你就应该能想到为什么一定要固定表示长度字节的长度呢,我们可以使用变长方式来表示长度的表示,比如:

第一个字节首位为0:即0XXXXXXX,表示长度就一个字节,最大128,表示128B
第一个字节首位为110,那么附带后面一个字节表示长度:即110XXXXX 10XXXXXX,最大2048,表示2K
第一个字节首位为1110,那么附带后面二个字节表示长度:即110XXXXX 10XXXXXX 10XXXXXX,最大131072,表示128K
依次类推
  上面提到的这种用法适合高富帅的程序员使用,一般呢,如果用作命名发送,两个字节就够了,如果还不放心4个字节基本就能满足你的所有要求,下面的例子我们将采用2个字节表示长度,目的只是给你一种思路,让你知道有这种方式来获取消息的结尾:

  服务端程序:
    public class SocketServer {
  public static void main(String[] args) throws Exception {
    // 监听指定的端口
    int port = 55533;
    ServerSocket server = new ServerSocket(port);

    // server将一直等待连接的到来
    System.out.println("server将一直等待连接的到来");
    Socket socket = server.accept();
    // 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
    InputStream inputStream = socket.getInputStream();
    byte[] bytes;
    // 因为可以复用Socket且能判断长度,所以可以一个Socket用到底
    while (true) {
      // 首先读取两个字节表示的长度
      int first = inputStream.read();
      //如果读取的值为-1 说明到了流的末尾,Socket已经被关闭了,此时将不能再去读取
      if(first==-1){
        break;
      }
      int second = inputStream.read();
      int length = (first << 8) + second;
      // 然后构造一个指定长的byte数组
      bytes = new byte[length];
      // 然后读取指定长度的消息即可
      inputStream.read(bytes);
      System.out.println("get message from client: " + new String(bytes, "UTF-8"));
    }
    inputStream.close();
    socket.close();
    server.close();
  }
}
此处的读取步骤为,先读取两个字节的长度,然后读取消息,客户端为:
    public class SocketClient {
  public static void main(String args[]) throws Exception {
    // 要连接的服务端IP地址和端口
    String host = "127.0.0.1";
    int port = 55533;
    // 与服务端建立连接
    Socket socket = new Socket(host, port);
    // 建立连接后获得输出流
    OutputStream outputStream = socket.getOutputStream();
    String message = "你好  yiwangzhibujian";
    //首先需要计算得知消息的长度
    byte[] sendBytes = message.getBytes("UTF-8");
    //然后将消息的长度优先发送出去
    outputStream.write(sendBytes.length >>8);
    outputStream.write(sendBytes.length);
    //然后将消息再次发送出去
    outputStream.write(sendBytes);
    outputStream.flush();
    //==========此处重复发送一次,实际项目中为多个命名,此处只为展示用法
    message = "第二条消息";
    sendBytes = message.getBytes("UTF-8");
    outputStream.write(sendBytes.length >>8);
    outputStream.write(sendBytes.length);
    outputStream.write(sendBytes);
    outputStream.flush();
    //==========此处重复发送一次,实际项目中为多个命名,此处只为展示用法
    message = "the third message!";
    sendBytes = message.getBytes("UTF-8");
    outputStream.write(sendBytes.length >>8);
    outputStream.write(sendBytes.length);
    outputStream.write(sendBytes);    
    
    outputStream.close();
    socket.close();
  }
}

这篇关于java文件读写的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!