黑马程序员_javaIO流

本文详细介绍了Java的IO流,包括字节流和字符流的分类,输入流和输出流的区别,以及常用方法。重点讲解了字符流的Writer和Reader,字节流的InputStream和OutputStream,以及他们的缓冲区实现BufferedReader和BufferedWriter。还提到了装饰设计模式在流中的应用,如LineNumberReader。此外,文章探讨了如何选择合适的流进行操作,并提供了文件复制、键盘输入到文件的示例,以及序列化接口Serializable的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

按操作数据分为字节流和字符流;

按流向分为输入流和输出流;

字符流基类
字符输入流(Reader):读取数据

int read(); 读取一个字符
int read(char[] buffer) 读取字符数组
字节输出流(Writer):写出数据

void write(int ch) 写入一个字符
void write(char[] buffer) 写入一个字符数组
void write(char[] buffer, int startIndex, int len) 写入字符数组的一部分
void write(String str) 写入一个字符串
void write(String str, int startIndex, int len) 写入字符串的一部分

字节流基类
字节输入流(InputStream):读取数据

int read() 读取一个字节
int read(byte[] buffer) 读取字节数组
字节输出流(OutputStream):写出数据

void write(int ch) 写入一个字节
void write(byte[] buffer) 写入一个字节数组
void write(byte[] buffer, int startIndex, int len) 写入字节数组的一部分

字符输出流演示:

需求:把文字存入硬盘中

import java.io.*;
class FileWriterDemo 
{
	public static void main(String[] args) throws IOException 
	{
		//创建一个FileWriter对象,该对象一初始化就必须明确被操作的文件
		//而且该文件会创建在指定目录下,如果该目录中有同名的文件,则文件会被覆盖
		//该步就是明确数据需要存放的目的地
		FileWriter fw = new FileWriter("12358.txt");
		//调用write方法,把字符串存入流中,而非直接存入目的地
		fw.write("你好!!");
		//刷新流对象中缓存的数据,将数据刷到目的地中
		fw.flush();
		//关闭流,先刷新一次
		fw.close();
		//关闭后无法向流中继续存入数据会报出流关闭异常
		//fw.write("asdd");

	}
}


IO异常的处理方式,为防止代码异常导致流无法关闭,所以必须使用finally关闭流。

FileWriter文件的续写:

示例:

import java.io.*;
class FileWriterDemo2 
{
	public static void main(String[] args) 
	{
		//演示对已有文件的续写
		FileWriter fw = null;
		try
		{
			fw= new FileWriter("demo1.txt",true);//后面加true表示对文件续写
			fw.write("ssssss\r\nnihao");
		}
		catch(IOException e)
		{	
			System.out.println(e);
		}
		finally//关闭流
		{
			try//可能会遇到异常
			{
				if(fw!=null)
				fw.close();
			}
			catch(IOException e)
			{
				System.out.println(e);
			}
		}

	}
}


字符读取流演示:

需求:把硬盘中的文字读到控制台,

可以用字符数组来提高效率,使用read(char[])方法,

如果使用read()方法读取单个字符效率低

演示:read(char[])

import java.io.*;
class FileReaderTest 
{
	public static void main(String[] args) 
	{
		
		FileReader fr = null;//定义一个空的读取类
		try
		{
			fr = new FileReader("12358.java");//初始化读取类
			char[] arr = new char[1024];//定义一个数组
			int num = 0;
			while((num=fr.read(arr))!=-1)//把文件读到字符数组中,判断文件中是否还有字符
			{
				System.out.println(new String(arr,0,num));//返回字符串
			}
		}
		catch (IOException e)
		{
			System.out.println(e);
		}
		finally//关闭流
		{
			try//可能会遇到异常,所以继续try
			{
				if(fr!=null)
					fr.close();
			}
			catch (IOException e)
			{
				System.out.println(e);
			}
		}
	}
}

演示:read()

import java.io.*;
class FileReaderTest 
{
	public static void main(String[] args) 
	{
		
		FileReader fr = null;//定义一个空的读取类
		try
		{
			fr = new FileReader("12358.java");//初始化读取类
			int ch = 0;
			while((ch=fr.read())!=-1)//判断文件中是否还有字符
			{
				System.out.println((char)ch);//返回字符串
			}
		}
		catch (IOException e)
		{
			System.out.println(e);
		}
		finally//关闭流
		{
			try//可能会遇到异常,所以继续try
			{
				if(fr!=null)
					fr.close();
			}
			catch (IOException e)
			{
				System.out.println(e);
			}
		}
	}
}

字符流缓冲区    目的:缓冲区是为了提高流的读取效率,所以没有空参数的构造函数。而且创建缓冲区前必须要先有流对象。

 原理:使用了读取缓冲区的read方法,将读取到的字符进行缓冲并判断换行标记,将标记前的缓冲数据变成字符串返回。

 写入换行使用BufferedWriter类中的newLine()方法。
    读取一行数据使用BufferedReader类中的readLine()方法。
    br.read():这个read方法是从缓冲区中读取字符数据,所以覆盖了父类中的read方法。
    br.readLine():另外开辟了一个缓冲区,存储的是原缓冲区一行的数据,不包含换行符。

BufferedReader,BufferedWriter提高文本操作效率,添加缓冲区

BufferedReader:

String readLine()读一行的方法

BufferedWriter:

void newLine()写入一个行分隔符

 

需求:对文件进行复制,要求高效

示例:

import java.io.*;
class CopyTextByBuf
{
	public static void main(String[] args) throws IOException
	{
		//通过缓冲区复制文本文件
		BufferedReader br = null;//定义一个空的缓冲区
		BufferedWriter bw = null;//定义一个空的缓冲区
		try
		{
			br = new BufferedReader(new FileReader("ReadIn.java"););//定义一个读累缓冲区,传入匿名文件读取类
			bw = new BufferedWriter(new FileWriter("1.txt"));//定义一个写类缓冲区,传入匿名文件写出类
			String line = null;//定义一个字符串记录读取到的一行
			while((line=br.readLine())!=null)//判断数据是否为空,使用缓冲区读一行的方法
			{
				bw.write(line);
bw.newLine();//记得换行
				bw.flush();//一定要记得刷新,用到缓冲区都要刷新
			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("复制失败");
		}
		finally
		{
			if(br!=null)
			{
				try
				{
					
						fls.close();
				}
				catch (IOException e)
				{
					throw new RuntimeException("读取关闭失败");
				}
			}
			if(bw!=null)
			{
				try
				{
					
						fos.close();
				}
				catch (IOException e)
				{
					throw new RuntimeException("写出关闭失败");
				}
			}
		}
		
	}
}

装饰设计模式和继承:

都是对功能进行扩展和增强。

装饰比继承灵活,装饰类和被装饰类都要属于同一个接口或者父类

LineNumberReader
    跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。
示例:

import java.io.*;

class LineNumberReaderDemo

{

public static void main(String[] args)throws IOException

{

//定义一个读取文件流

FileReader fr = new FileReader("HashMap.java");

//定义一个行号的缓冲字符输入流

LineNumberReader lnr = new LineNumberReader(fr);

//设置起始行号为1000

lnr.setLineNumber(1000);

//定义一个空字符串,来接收读取的一行数据

String line = null;

while((line=lnr.readLine())!=null)

{

System.out.println(lnr.getLineNumber()+":::"+line);

//得到行号和该文件的数据

}

}

}

字节流基本操作和字符流相同,但是字节流还可以操作其他媒体文件

字节流的两种读取方式

演示:

import java.io.*;
class ReadIn 
{
	public static void main(String[] args) throws IOException
	{
		InputRead1();
		System.out.println("---------------------");
		InputRead2();
	}
	public static void InputRead1()throws IOException
	{
		//这种方式效率比较高 建议使用
		FileInputStream fis = new FileInputStream("1.txt");//定义一个字节输出流
		byte[] buf = new byte[1024];//定义一个字节数组,来当容器
		int len = 0;//定义一个数,用来记住存入字节数组中的个数
		while((len=fis.read(buf))!=-1)//判断是否读到结束标记
		{
			System.out.println(new String(buf,0,len));
		}
		fis.close();//关闭读取流
	}
	public static void InputRead2()throws IOException
	{
		FileInputStream fis = new FileInputStream("1.txt");//定义一个字节输出流
		int ch = 0;//定义一个数,接收读取到的字节数
		while((ch=fis.read())!=-1)//判断是否读到结束标记
		{
			System.out.print((char)ch);
		}
		fis.close();//关闭读取流
	}
}

出现?号的原因是read一次读取一个字节,直接打印到控制台,而默认的GBK码表一个中文是两个字节。

字节流的缓冲区

BufferedInputStream,BufferedOutputStream;提高文本操作效率,添加缓冲区,凡是用到缓冲区,都要记得刷新。

示例:复制图片,需要缓冲区

import java.io.*;
class Copypic 
{
	public static void main(String[] args) 
	{
		//复制图片
		BufferedInputStream bls = null;
		BufferedOutputStream bos = null;
		try
		{
			bls=new BufferedInputStream(new FileInputStream("2.png"));
			bos=new BufferedOutputStream(new FileOutputStream("3.png"));
			int ch = 0;
			while((ch=bls.read())!=-1)
			{
				bos.write(ch);
			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("复制失败");
		}
		finally
		{
			try
			{
				if(bls!=null)
					bls.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("读取关闭失败");
			}
			try
			{
				if(bos!=null)
					bos.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("写出关闭失败");
			}
		}
	}
}

转换流:

InputStreamReader,字节流对象转换成字符流对象,解码

BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream));

OutputStreamWriter,字符流对象转换成字节流对象,编码

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream));

疑问:有这么多流我们应该使用那些流呢?

通过三个明确来完成对流的操作

1.明确源和目的

源:输入流 InputStream,Reader

目的:输出流 OutputStream,Writer

2.操作的数据是否纯文本

是:字符流

不是:字节流

3.当体系明确后,在明确使用哪个具体的对象

通过设备来区分:

源设备:内存,硬盘,键盘

目的设备:内存,硬盘,键盘

例如:读取键盘录入,显示在控制台上,

1、明确源和目的。
         源:InputStream Reader
        目的:OutputStream Writer
    2、是否是纯文本?
         是!
         源:Reader
         目的:Writer
    3、明确具体设备。
         源:
             键盘:System.in
         目的:
             硬盘:System.out
         InputStream in = System.in;
         OutputStream out = System.out;
    4、需要额外功能么?
         需要转换流。因为都是字节流,但是操作的却是文本数据。所以使用字节流操作起来更为便捷。
         InputSreamReader isr = new InputStreamReader(System.in);
        OutputStreamWriter osw = new OutputStreamWriter(System.out);
         需要,高效。
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

 

 题目:读取键盘录入信息,并大写入到一个文件中
    1、明确源和目的。
         源:InputStream Reader
         目的:OutputStream Writer
    2、是否是纯文本?
         是!
         源:Reader
        目的:Writer
    3、明确具体设备。
         源:
             键盘:System.in
         目的:
             硬盘:File
         FileReader fr = new System.in;
         FileWriter fw = new FileWriter("b.txt");
    这样做可以完成,但是麻烦。将读取的字节数据转成字符串,再由字符流操作。
    4、需要额外功能吗?
         需要,转换。将字节流转成字符流,因为明确的源是Reader,这样操作文本数据更快捷。
         InputStreamReader isr = new InputStreamReader(System.in);
         FileWriter fw = new FileWriter("2.txt");
         还需要功能吗?
         需要,高效。
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bufw = new BufferedWriter(new FileWriter("2.txt"));

示例:


import java.io.*;
class covStream 
{
	public static void main(String[] args) throws  IOException
	{
//因为是文本为提高效率使用字节转换流接收键盘录入
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));	
//提高效率使用缓冲流写到硬盘上
		BufferedWriter bw = new BufferedWriter(new FileWriter("2.txt"));
		String line=null;
		while((line=br.readLine())!=null)
		{
			if("over".equals(line))
				break;
			bw.write(line.toUpperCase());
			bw.newLine();
			bw.flush();
		}
		br.close();
	}
}




通过System类的setIn,setOut方法可以对默认设备进行改变。

示例:

import java.io.*;
class covStream 
{
	public static void main(String[] args) throws  IOException
	{
		//改变输入对象值
		System.setIn(new FileInputStream("Copypic.java"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//改变输出对象值
		System.setOut(new	PrintStream(new FileOutputStream("3.txt")));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( System.out));
			String line=null;
		while((line=br.readLine())!=null)
		{
			if("over".equals(line))
				break;
			bw.write(line.toUpperCase());
			bw.newLine();
			bw.flush();
		}
		br.close();

	}



编码表:

任何Java识别的字符数据使用的都是Unicode码表,但是FileWriter写入本地文件使用的是本地编码,也就是GBK码表。

而OutputStreamWriter可以只用指定的编码把写入流中的字符编成字节

当使用UTF-8编码时。用GBK码表是解不出来的,因为UTF-8码表一个中文3个字节,而GBK是2个字节,如果是”你好”用UTF-8编码,使用GBK解码会显示三个GBK中两个字节对应的字符,相反如果用GBK给“你好”编码,用UTF-8解码,会显示两个??。

示例:

mport java.io.*;
class UnicodeDemo 
{
	public static void main(String[] args) throws IOException
	{
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("1.txt"),"UTF-8");
		osw.write("你好");
		osw.close();
	}
}


import java.io.*;

class UnicodeDemo1

{

public static void main(String[] args) throws IOException

{

BufferedReader br = new BufferedReader(new FileReader("1.txt"));

String line = br.readLine();

System.out.println(line);

br.close();

}

}


原因:因为1.txt文件中是UTF-8编码的“你好”,有6个字节。
 而FileReader类是用GBK编码进行读取,6个字节代表3个字符,按照GBK进行解码,因此才出现如上结果。
示例2:

import java.io.*;
class UnicodeDemo2
{
	public static void main(String[] args) throws IOException
	{
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("2.txt"),"GBK");
		osw.write("你好");
		osw.close();		
	}
}

import java.io.*;
class UnicodeDemo 
{
	public static void main(String[] args) throws IOException
	{
		InputStreamReader isr = new InputStreamReader(new FileInputStream("2.txt"),"UTF-8");
		char[] buf = new char[10];
		int len = isr.read(buf);
		System.out.println(new String(buf,0,len));		
	}
}


 原因:由于2.txt文件中是GBK编码的“你好”,4个字节。
   使用InputStreamReader类是用UTF-8编码进行读取,由于GBK编码的字节使用UTF-8没有对应的字符,因此使用“?”进行代替。


File类


File类是用来操作文件与文件夹的属性信息,把文件或者文件夹封装成了对象,File对象可以作为参数传递给流的构造函数。
构造方法:

File f = new File(“f:\\abc\\a.txt”)

 

File f2 = new File(“f:\\abc\\”,”b.txt”)

 

File d = new File(“f:\\abc”)

 

File f3 = new File(d,“c.txt”)

 

File文件中有个特殊的分隔符字段separator

File f4 = new 

File(“f:”+File.separator+”abc”+File.separator+”a.txt”)

上面这种方法可跨平台使用

 

File类的常见方法

1.创建

boolean createNewFile:在指定位置创建文件,如果文件已 经存在,则不创建,返回false。和输出流不一样,输出流对 象一旦建立,就会创建文件,若文件已存在,则覆盖。

boolean mkdir():创建文件夹,只创建一级文件夹。

boolean mkdirs():创建多级文件夹。

2.删除

boolean delete():删除文件,删除成功,返回true,删除失败返回false,如:正在使用文件就无法删除。

void deleteOnExit():在程序退出时删除文件。

3.判断

判断文件对象是文件还是目录时,必须先判断该文件封装的内容是否存在,通过exists判断。

boolean exists():文件是否存在。

boolean isFile():是否是文件。

boolean isDirectory():是否是目录。

boolean isHidden():是否是隐藏文件。

boolean isAbsolute():是否为绝对路径名。

4.获取信息

String getName();返回名称。

String getPath();返回路径名字,如果是相对路径则返回名 字,如果是绝对路径则返回其路径。

String getParent();返回绝对路径中的父目录,如果是相对 路径,则返回null。如果相对路径中有上一层目录则返回该 目录。

String getAbsolutePath():无论绝对还是相对路径,都返 回绝对路径。

long lastModified():上一次修改时间。

long length();返回长度。

static File[] listRoot:获取盘符;

String[] list:返回目录中的文件和文件夹,包括隐藏文件

使用list必须要求File对象封装的是一个目录,而且其目 录必须存在。

示例:

import java.io.*;
class FileDemo 
{
	public static void main(String[] args) throws IOException
	{
		File file1 = new File("1.txt");//新建一个文件类
		File file2 = new File("f:\\2.txt");//新建一个文件类
		//if(file1.exists())//判断是否存在
			boolean b1 = file1.createNewFile();//创建文件,如果已存在则不创建
		//if(file2.exists())//判断是否存在
			boolean b2 = file2.createNewFile();//创建文件,如果已存在则不创建
		String name = file1.getName();//得到名字
		String path1 = file1.getPath();//返回路径名字,如果是相对路径则返回名	字,如果是绝对路径则返回其路径。
		String path2 = file1.getPath();//返回路径名字,如果是相对路径则返回名	字,如果是绝对路径则返回其路径。
		String absPath1 = file1.getAbsolutePath();//无论绝对还是相对路径,都返	回绝对路径。
		String absPath2 = file2.getAbsolutePath();//无论绝对还是相对路径,都返	回绝对路径。
		long len1 = file1.length();//得到长度
		long len2 = file2.length();//得到长度
		long time1 = file1.lastModified();//上一次修改时间。
		long time2 = file2.lastModified();//上一次修改时间。
		String parentName1 = file1.getParent();//返回绝对路径中的父目录,如果是相对	路径,则返回null。如果相对路径中有上一层目录则返回该	目录。
		String parentName2 = file2.getParent();//返回绝对路径中的父目录,如果是相对	路径,则返回null。如果相对路径中有上一层目录则返回该	目录。
		System.out.println(b1);
		System.out.println(b2);
		System.out.println(name);
		System.out.println(path1);
		System.out.println(path2);
		System.out.println(absPath1);
		System.out.println(absPath2);
		System.out.println(len1);
		System.out.println(len2);
		System.out.println(time1);
		System.out.println(time2);
		System.out.println(parentName1);
		System.out.println(parentName1);


	}
}

重命名示例:

import java.io.*;
class FileDemo1 
{
	public static void main(String[] args) 
	{
		File file1 = new File("f:\\1.txt"); //定义一个file文件类
		File file2 = new File("f:\\GG.txt");//定义一个file文件类
		boolean b = file1.renameTo(file2);//修改file1的名字为file2中的名字和路径
		System.out.println(b);//输出是否修改成功
	}
}

获取目录下的文件和文件夹:

示例:

import java.io.*;
class FileDemo2 
{
	public static void main(String[] args) 
	{
		//需求读取C盘下的目录和文件
		File file = new File("c:\\");
		String [] names = file.list();//把目录和文件名存入字符串数组中
		for(String name : names)//通过高级for循环迭代取出
		{
			System.out.println(name);
		}
	}
}



递归:

函数自身调用了自身称之为递归;

使用场景:

一个功能被重复使用,而每一次使用都和上次的调用有关,这时候就可以用递归来解决问题。

注意:

1.条件一定要明确,不然栈内存溢出

2.一定要注意递归的次数,不要太多次

示例:

列出目录中的所有文件,即文件夹中的文件也要列出

 

import java.io.*;
class getAllListFiles 
{
	public static void main(String[] args) 
	{
		 File f = new File("F:\\javadm");
		 getAll(f,0);
		
	}
	public static String getLevel(int level)
	{
		//获得等级
		StringBuilder sb = new StringBuilder();//定义一个容器
		sb.append("|--");
		for(int i=0;i<level;i++)
		{
			sb.insert(0,"|  ");
			//sb.append("|--");
		}
		return sb.toString();
	}
	public static void getAll(File f,int level)
	{
		//获取目录下所有文件夹和文件
		System.out.println(getLevel(level)+f);
		level++;
		 File[] f1 = f.listFiles();
		 for(File fs : f1)
   		 {
			if(fs.isDirectory())//判断是否为目录
			{
				getAll(fs,level);//递归
			}
			else
				System.out.println(getLevel(level)+fs);
		 }
	}
}


Properties:

示例:

import java.io.*;
import java.util.*;
class PropertiesDemo 
{
	public static void main(String[] args) throws IOException
	{
		setProp();
	}
	public static void setProp()throws IOException
	{
		//要求:把文本上的信息用setProperties修改后保存起来。
		FileInputStream fis = new FileInputStream("2.txt");
		Properties p = new Properties();
		p.load(fis);//从输出流中读取属性列表
		FileOutputStream fos = new FileOutputStream("2.txt");
		p.setProperty("wangwu","GG");//设置键值对
		p.store(fos,"信息名");//把读取到的属性列表写入输出流
		System.out.println(p);
		Set<String> st = p.stringPropertyNames();//返回列表中的键集,
		for(String s : st)
		{
			System.out.println(s+"::"+p.getProperty(s));//通过键得到值
		}

	}
}


PrintStream:字节打印流

构造函数可以接收的类型。

1.file对象.File

2.字符串路径。String

3.字节输出流。OutputStream

import java.io.*;
class Demo 
{
	public static void main(String[] args)throws Exception 
	{
		PrintStream ps = new PrintStream("demo.txt");
		//打印转换后的字符
		ps.write(100);
		//打印原字符
		ps.print(100);
	}
}

PrintWriter:,字符打印流

构造函数可以接收的类型。

1.file对象.File

2.字符串路径。String

3.字节输出流。OutputStream,在后面添加true表示自动刷新

4.字符输出流,Writer,在后面添加true表示自动刷新

示例:

mport java.io.*;
class Demo 
{
	public static void main(String[] args) throws IOException
	{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//键盘录入
		PrintWriter pw = new PrintWriter(new FileOutputStream("fls.txt"),true);//定义一个自动刷新的打印流
		String line = null;
		while((line=br.readLine())!=null)
		{
			if(line.equals("over"))//结束标记
				break;
			pw.println(line.toUpperCase());//字符串大写
		}
		pw.close();
		br.close();
	}
}

SequenceInputStream:表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

即对多个文件进行合并

示例:

import java.util.*;
import java.io.*;
class SequenceDemo 
{
	public static void main(String[] args) throws IOException
	{
		//把多个文件写入一个文件
		Vector<InputStream> v = new Vector<InputStream>();
		//把流存入集合
		v.add(new FileInputStream("1.txt"));
		v.add(new FileInputStream("2.txt"));
		v.add(new FileInputStream("3.txt"));
		//得到枚举对象
		Enumeration<InputStream> en = v.elements();
		//建立合并流
		SequenceInputStream sis = new SequenceInputStream(en);
		//确认输出目的
		FileOutputStream fos = new FileOutputStream(new File("4.txt"));
		byte[] b = new byte[1024];
		int ch =0;
		while((ch=sis.read(b))!=-1)
		{
			fos.write(b,0,ch);
		}
		fos.close();
		sis.close();
	}
}

对象的序列化:即对象的持久存储:想要序列化必须要实现序列化接口:Serializable

没有方法的接口称为标记接口

 

public static final long serialVersionUID = 42L;

使用上面的代码,可以定义一个固定标记,而不会因为对象类,有些小改动,就无法识别。

注意:静态无法被序列化,因为序列化是在堆内存中,而静态在方法区

前面加transient也不会被序列化,保证其值在堆内存中,也不会被序列化

示例:

mport java.io.*;
class ObjectStreamDemo 
{
	public static void main(String[] args) throws Exception
	{
		//writeObject();
		readObject();
	}
	//把对象序列化,即持久化
	public static void writeObject()throws Exception
	{
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("per.person"));
		oos.writeObject(new person("zhangsan",18));
		oos.close();

	}
	//把序列化对象读取
	public static void readObject()throws Exception
	{
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("per.person"));
		person p = (person)ois.readObject();
		System.out.println(p);
		ois.close();

	}
}
//对象想要序列化必须实现Serializable接口
class person implements Serializable
{
	public static final long serialVersionUID = 42L;
	private String name ;
	private int age;
	person(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
	public String toString()
	{
		return name+":::::"+age;
	}
}

文件切割与合并:

示例:

import java.io.*;
import java.util.*;
class SplitFileDemo 
{
	public static void main(String[] args) throws IOException
	{
split();
		fuhe();
	}
	//把多个文件合成一个文件
	public static void fuhe() throws IOException
	{
		//使用ArrayList效率高
		ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
		for(int i=1;i<=5;i++)
		{
			al.add(new FileInputStream(i+".part"));
		}
		final Iterator<FileInputStream> it = al.iterator();//因为是局部变量若想让匿名内部类使用必须final修饰
		Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()//覆盖枚举接口方法
		{
			public boolean hasMoreElements()
			{
				return it.hasNext();
			}
			public FileInputStream nextElement()
			{
				return it.next();
			}
		};
		SequenceInputStream sis =new SequenceInputStream(en);//定义合并流
		FileOutputStream fos = new FileOutputStream(new File("0.mp3"));
		byte[] b = new byte[1024];
		int ch =0;
		while((ch=sis.read(b))!=-1)
		{
			fos.write(b,0,ch);
		}
		fos.close();
		sis.close();

	}
	//把文件切割成1M大小的若干文件
	public static void split()throws IOException
	{
		FileInputStream  fis = new FileInputStream("1.mp3"); 
		FileOutputStream fos = null;
		byte[] buf = new byte[1024*1024];//切成1M大小
		int len = 0;
		int count=1;
		while((len=fis.read(buf))!=-1)
		{
			fos = new FileOutputStream((count++)+".part");//定义文件名字
			fos.write(buf,0,len);
			fos.close();
		}
		fis.close();
	}
}

RandomAccessFile:

随机访问文件,自身具备读写方法

该类不算是IO体系中子类,而是直接继承自Object.

但是它是IO包中成员,因为其具备读和写的功能,

内部封装了一个数组,而且通过指针对数组的元素进行操作

可以通过getFilePointer获取指针位置

同时可以通过seek改变指针位置

其实完成读写的原理就是内部封装了字节输入流和输出流

通过构造函数看出该类只能操作文件

如果要操作文件不存在,就会创建,如果存在,不会覆盖。

因为有seek改变指针位置所以可以取该数组中的任意位置的值

同时可以改变任意位置的值,在任意位置进行操作。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值