Java IO输入输出流 笔记

		String s = "慕课ABC";
		byte[] bytes1 = s.getBytes();//转换成字节序列用的是项目默认的编码 ,编码GBK
		for(byte b : bytes1)
		{
			//把字节(转换成)int以16进制的方式显示, 只显示后8位
			System.out.println(Integer.toHexString(b & 0xff) + " ");
		}
		//gbk编码中文占用两个字节,英文占用1个字节
		//utf-8编码中文占用3个字节,英文占用1个字节
		byte[] bytes2 = s.getBytes("utf-8");
		for(byte b : bytes2)
		{
			System.out.print(Integer.toHexString(b & 0xff) + " ");
		}

//java是双字节编码, utf-16be编码 ,它中文占用两个字节,英文也是占用两个字节

当你的字节序列是某种编码时,这时候想把字节序列变成字符串,也需要用这种编码方式,否则会出现乱码。

String str2 = new String(bytes4, "utf-16be");

文本文件就是字节序列,可以是任意编码的字节序列。如果我们在中文机器上直接创建(如果复制过去则可以识别)文本文件,该文本文件只认识ANSI编码。

File

java.io.File类用于表示文件(目录)

File类只用于表示文件(目录)的信息(名称,大小)等,不能用于文件内容的访问

		File file = new File("D:\\javaio");
		//System.out.println(file.exists());//文件是否存在

		if(!file.exists())//是否存在
			file.mkdir();//创建目录     //file.mkdirs多级目录
		else
			file.delete();

		System.out.println(file.isDirectory());//是否是目录,是目录返回true
		System.out.println(file.isFile());//是否是文件

		//File file2 = new File("D:\\javaio\\日记1.txt");
		File file2 = new File("D:\\javaio", "日记1.txt");
		if( !file2.exists())
			try{
			   file2.createNewFile();//创建文件
		}catch(IOException e){
			e.printStackTrace();
		}
		else
			file2.delete();//文件删除掉

		//常用的file对象的API
		System.out.println(file);//file.toStrint()的内容 ,目录
		System.out.println(file.getAbsolutePath());
		System.out.println(file.getName());//文件或目录的名字
		System.out.println(file.getParent());//父目录的路径

	//列出指定目录下(包括其子目录)的所有文件
	public static void listDirectory(File dir) throws IOException
	{
		if(!dir.exists())//不存在
		{
			throw new IllegalArgumentException("目录"+dir+"不存在");
		}
		if(!dir.isDirectory())//不是目录
		{
			throw new IllegalArgumentException(dir+"不是目录");
		}
		String[] filenames = dir.list(); //list()方法用于列出当前目录下的子目录和文件名称,字符串数组,包含子目录的名称,不包含子目录下的内容
		for(String string : filenames)
		{
			System.out.println(string);
		}
		//如果要遍历子目录下的内容,就需要构造成file对象做递归操作,File提供了直接返回file对象的API
		File[] files = dir.listFiles();//返回的是直接子目录(文件)的抽象,不会做递归
		if(files != null && files.length > 0)
		{
			for( File file : files)
			{
				if(file.isDirectory())
				{
					listDirectory(file);//递归操作
				}
				else
					System.//输出
			}
		}
	}

RandomAccessFile 

java提供的对文件内容的访问,既可以读文件,也可以写文件,支持随机访问文件,可以访问文件的任意位置。

(1)java文件模型: 在硬盘上的文件是byte byte byte存储的,是数据的集合

(2)打开文件有两种模式   "rw"读写   "r"只读

RandomAccessFile raf = new RandomAccessFile(file, "rw");

文件指针,打开文件时,pointer = 0;

(3)写文件

raf.write(int)  只写一个字节(只能写int的后8位),同时指针指向下一个位置,准备再次写入

(4)读方法

int b = raf.read() 读一个字节

(5)文件读写完成后一定要关闭 (可能会有意想不到的错误)

文件读写过程:

File demo = new File("D:\\demo");
		if(!demo.exists())
			demo.mkdir();
		File file = new File(demo, "raf.dat");
		if(!file.exists())
			file.createNewFile();
		RandomAccessFile raf = new RandomAccessFile(file, "rw");
		System.out.println(raf.getFilePointer());//获得指针位置,此时值为0
		raf.write('A');//写A的后8位写进去,只写了一个字节
		System.out.println(raf.getFilePointer());//获得指针位置,此时值位1

		int i = 0x7fffffff;
		//用write方法每次写一个字节,如果要把i写进去就得写4次
		raf.write(i >>> 24 );//高8位
		raf.write(i >>> 16 );
		raf.write(i >>> 8 );
		raf.write(i);
		System.out.println(raf.getFilePointer());//获得指针位置,此时为5

		//可以直接写一个int
		raf.writeInt(i);

		String s = "中";
		byte[] gbk = s.getBytes("gbk");
		raf.write(gbk);
		System.out.println(raf.length());

		//读文件,必须把指针移动到头部
		raf.seek(0);
		//把文件中的内容都读到字节数组中,一次性读取
		byte[] buf = new byte[(int)raf.length()];
		raf.read(buf);
		System.out.println(Arrays.toString(buf));//输出[65, 127, -1, -1, -1, 127, -1, -1, -1, -42, -48] 65是’A‘

		String s1 = new String(buf,"gbk");
		System.out.println(s1);

		for(byte b : buf)
		{
			System.out.println(Integer.toHexString(b & 0xff) + " ");
		}
		raf.close();//关闭文件

IO流(输入流,输出流)

字节流,字符流

1.字节流

(1) InputStream  
OutputStream
 抽象类

InputStream 抽象了应用程序读取数据的方式

OutputStream 抽象了应用程序写出数据的方式

(2)EOF = End 读到-1就读到结尾

(3)输入流 键盘输入是输入流

基本方法:

int b = in.read();//读取一个字节无符号填充到int的低8位,其他位补0

in.read(byte[] buf)读取数据填充到字节数组buf

in.read(byte[] buf,int start, int size)读取数据到字节数组buf中,从start位置开始放,最多放多少个

(4)输出流

out.write(int b)写出一个byte到流,写的是b的低8位

out.write(byte[] buf)将字节数组buf都写入到流

out.write(byte[], int start, int size)

(5)子类 FileInputStream  -->具体实现了在文件上读取数据

/读取文件内容,按照16进制输出到控制台,并且每输出10个byte换行, 一个一个字节读
public static void printHex(String fileName) throws IOException
{
	FileInputStream in = new FileInputStream(fileName);//把文件作为字节流进行读操作
	int b;
	int i = 1;
	while((b = in.read()) != -1)//读到一个字节
	{
		System.out.print(Integer.toHexString(b) + " ");
		if( i ++ % 10 == 0)
		{
			System.out.println();
		}
	}
	in.close();

}

//批量读字节
public static void printHexByByteArray(String fileName) throws IOException
{
	FileInputStream in = new FileInputStream(fileName);//把文件作为字节流进行读操作
	byte[] buf = new byte[8*1024];
	//从in中批量读取字节,放入buf这个字节数组中,从0个位置开始放,最多放buf.length个
	//返回的是读到的字节的个数
	/*
	int bytes = in.read(buf, 0, buf.length);//一次性读完,说明字节数组足够大
	int j = 1;
	for(int i = 0; i < bytes; i ++)
	{
		if(buf[i] <= 0xf)
			System.out.print("0");
		System.out.print(Integer.toHexString(buf[i]) + " ");
		if( j ++ % 10 == 0)
		{
			System.out.println();
		}
	}
	*/
	//数组不够大怎么办,解决方法
	int bytes = 0;
	int j = 1;
	while((bytes = in.read(buf, 0, buf.length)) != -1)
	{
		for(int i = 0; i < bytes; i ++)
		{
			System.out.print(Integer.toHexString(buf[i] & 0xff)+ " ");
			if(j++ % 10 == 0)
				System.out.println();
		}
	}
	in.close();
}

单字节读取不适合大文件,大文件效率很低

批量字节读取,对大文件效率高,也是我们最常用的读文件的方式

(6)FileOutputStream实现了向文件中写出byte数据的方法

//如果该文件不存在,则直接创建,如果存在,删除后创建
FileOutputStream out = new FileOutputStream("demo/out.dat");  //如果要追加,则参数为"demo/out.data', true  true代表是否追加
out.write('A');//写出了'A'的低8位
out.write('B');//写出了'B'的低8位
int a = 10;//write只能写8位,写int需要写四次
out.write(a >>> 24);
out.write(a >>>16);
out.write(a >>> 8);
out.write(a);

byte[] gbk = "中国".getBytes("gbk");
out.write(gbk);
out.close();
/将一个文件拷贝到另一个文件    最快的
	public static void copyFile(File srcFile, File destFile) throws IOException
	{
		if( !srcFile.exists())
		{
			throw new IllegalArgumentException("文件:"+ srcFile + "不存在");
		}
		if(!srcFile.isFile())
		{
			throw new IllegalArgumentException("文件:" + srcFile + "不是文件");
		}

		FileInputStream in = new FileInputStream(srcFile);
		FileOutputStream out = new FileOutputStream(destFile);
		byte[] buf = new byte[8 * 1024];
		int b;
		while((b = in.read(buf, 0, buf.length)) != -1)
		{
			out.write(buf, 0, b);
			out.flush();//清空输出流
		}
		in.close();
		out.close();

	}

(7) DataOutputStream  DataInputStream

对"流“功能的扩展,可以更加方面的读取int long 字符等类型数据

DataOutStream 来说  writeInt()/ writeDouble /  writeUTF()

<span style="white-space:pre">		</span>String file = "demo/dos.dat";
		DataOutputStream dos = new DataOutputStream(
			new FileOutputStream(file));
		dos.writeInt(10);
		dos.writeInt(-10);
		dos.writeLong(100);
		dos.writeDouble(10.5);
		//采用utf-8编码写出
		dos.writeUTF("中国");
		//以utf-16be编码写出
		dos.writeChars("中国");
		dos.close();

		DataInputStream dis = new DataInputStream(new FileInputStream(file));
		int i = dis.readInt();

(8) BufferedInputStream  
BufferedOutputStream

这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入或者读取操作时,都会加上缓冲,

这种流模式提高了IO的性能。

//从应用程序中把数据放入文件,相当于把一缸水倒入到另一个缸中

FileOutputStream  -->write()相当于一滴一滴得把水”转移“过去

DataOutputStream   -->writeXxx()方法会方便一些,相当于一瓢一瓢的转移过去

BufferedOutputStream --->writeXxx()方法更方便,相当于一瓢一瓢水先放入桶中,再从桶中倒入到另一个缸中,性能提高

public static void copyFileByBuffer(File srcFile, File destFile) throws IOException
{
	//利用带缓冲的字节流进行文件的拷贝
	BufferedInputStream bis = new BufferedInputStream(
		   new FileInputStream(srcFile));
	BufferedOutputStream bos = new BufferedOutputStream(
		   new FileOutputStream(destFile));

	int c;
	while((c = bis.read()) != -1)
	{
		bos.write(c);
		bos.flush();//刷新缓冲区,必须写
	}
	bis.close();
	bos.close();

}

2.字符流

1)编码问题

2)认识文本和文本文件

java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码)

文件是 byte byte byte.... 的数据序列

文本文件是文本(char)序列按照某种编码方案(utf-8 utf-16be,gbk)序列化为byte的存储结果

3)字符流(Reader Writer) 操作的是文本文件

字符的处理,一次处理一个字符

字符的底层仍然是基本的字节序列。

字符流的基本实现

InputStreamReader 完成byte流解析为char流,按照编码解析

OutputStreamReader 提供char流到byte流,按照编码处理

		FileInputStream in = new FileInputStream("d:\\sr.txt");
		InputStreamReader isr = new InputStreamReader(in);//默认项目的编码,操作时要写文件的编码

		FileOutputStream out = new FileOutputStream("d:\\sx.txt");
		OutputStreamWriter osw = new OutputStreamWriter(out);
		/*int c;
		while((c = isr.read())!= -1){
			System.out.print((char)c);
		}
		*/
		char[] buffer = new char[8 * 1024];
		int c;
		//批量读取,放入buffer这个字符数组,从第0个开始放,最多放buffer.length个
		//返回的是读到的字符的个数
		while((c = isr.read(buffer, 0,buffer.length))!= -1){
			String s = new String(buffer, 0, c);
			osw.write(buffer, 0, c);
			System.out.print(s);
		}
		osw.close();
		isr.close();

FileReader/ FileWriter 

FileReader fr = new FileReader("D:\\sr.txt");
		FileWriter fw = new FileWriter("D:\\sx.txt");//可以添加一个参数,true是否追加
		char[] buffer = new char[2056];
		int c;
		while((c = fr.read(buffer, 0, buffer.length))!= -1 ){
			fw.write(buffer, 0, c);
			fw.flush();
		}
		fr.close();
		fw.close();

方便,但是不能正确读取不是默认编码的文件,否则乱码,FileReader fr = new FileReader("D:\\sr.txt");没有第二个参数(编码方式)

字符流的过滤器

BufferedReader -->一次读一行

BufferedWriter / PrintWriter  --->写一行

//对文件进行读写操作
		BufferedReader br = new BufferedReader(
				new InputStreamReader(new FileInputStream("D:\\sr.txt")));
		/*BufferedWriter bw = new BufferedWriter(
				new OutputStreamWriter(new FileOutputStream("D:\\sx.txt")));
		*/
		PrintWriter pw = new PrintWriter("D:\\sx.txt");
		String line;
		while((line = br.readLine()) != null){
			System.out.println(line);//一次读一行,并不能识别换行
			//bw.write(line);
			//单独写出换行操作
			//bw.newLine();
			//bw.flush();
			pw.println(line);
			pw.flush();
		}
		br.close();
		//bw.close();
		pw.close();

3 .对象的序列化,反序列化

1)对象序列化,就是将Object转换成byte序列,反之叫对象的反序列化

2)序列化流(ObjectOutStream),是过滤流  ---writeObject方法

反序列化流(ObjectInputStream),---readObject方法

3)序列化接口(Serializable)

对象必须实现序列化接口,才能进行序列化,否则将出现异常

这个接口,没有任何方法,只是一个标准

public class Student implements Serializable {
	private String stuno;
	private String stuname;
	private int stuage;
	public Student(){}

	public Student(String stuno, String stuname, int stuage) {
		super();
		this.stuno = stuno;
		this.stuname = stuname;
		this.stuage = stuage;
	}

	public String getStuno() {
		return stuno;
	}
	public void setStuno(String stuno) {
		this.stuno = stuno;
	}
	public String getStuname() {
		return stuname;
	}
	public void setStuname(String stuname) {
		this.stuname = stuname;
	}
	public int getStuage() {
		return stuage;
	}
	public void setStuage(int stuage) {
		this.stuage = stuage;
	}
	@Override
	public String toString() {
		return "Student [stuage=" + stuage + ", stuname=" + stuname
				+ ", stuno=" + stuno + "]";
	}

}

public static void main(String[] args) throws IOException, ClassNotFoundException{
		String file = "D:\\1.dat";
		//1.对象的序列化
		/*ObjectOutputStream oos = new ObjectOutputStream(new
				FileOutputStream(file));
		Student stu = new Student("1002", "sr", 12);
		oos.writeObject(stu);
		oos.flush();
		oos.close();
		*/

		//对象的反序列化
		ObjectInputStream ois = new ObjectInputStream(new
				 FileInputStream(file));
		Student stu = (Student)ois.readObject();
		System.out.println(stu);
		ois.close();

	}

private  transient int stuage;//该元素不会进行jvm默认的序列化,  有些情况下有些变量不需要放在网络上传输

不代表不能序列化,也可以自己完成这个元素的序列化

4)

import java.io.Serializable;
import java.util.jar.JarException;

public class Student implements Serializable {
	private String stuno;
	private String stuname;
	private  transient int stuage;//该元素不会进行jvm默认的序列化
	public Student(){}

	public Student(String stuno, String stuname, int stuage) {
		super();
		this.stuno = stuno;
		this.stuname = stuname;
		this.stuage = stuage;
	}

	public String getStuno() {
		return stuno;
	}
	public void setStuno(String stuno) {
		this.stuno = stuno;
	}
	public String getStuname() {
		return stuname;
	}
	public void setStuname(String stuname) {
		this.stuname = stuname;
	}
	public int getStuage() {
		return stuage;
	}
	public void setStuage(int stuage) {
		this.stuage = stuage;
	}
	@Override
	public String toString() {
		return "Student [stuage=" + stuage + ", stuname=" + stuname
				+ ", stuno=" + stuno + "]";
	}

	private void writeObject(java.io.ObjectOutputStream s)
			throws java.io.IOException{
		s.defaultWriteObject();//把jvm能默认序列化的元素进行序列化操作
		s.write(stuage);//自己完成stuage的序列化

	}

	private void readObject(java.io.ObjectInputStream s)
	throws  java.io.IOException, ClassNotFoundException{
		s.defaultReadObject();//把jvm能默认序列化的元素进行反序列操作
	    this.stuage = s.readInt();//自己完成stuage的反序列化
	}

}

5)序列化中 子类和父类构造函数的调用

一个类实现了序列化接口,其子类都可以进行序列化。

对子类对象进行反序列操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被调用

时间: 2024-12-16 04:57:53

Java IO输入输出流 笔记的相关文章

java.IO输入输出流:过滤流:buffer流和data流

java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? 不带缓冲的操作,每读一个字节就要写入一个字节. 由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低. 带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里. 等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多! 这就是两者的区别

Java IO输入/输出流的套接

缓冲字符流BufferedInputStream / BufferedOutputStream 文件操作流 InputStream / OutputStream java 输入输出流的套接,测试一下流链的速度 因为节点流在程序中并不是很常用,一般常通过过滤流将多个流套接在一起,利用各流的特性共同处理数据,套接的多个流构成了一个流链: 我们来分析他们的运行时间.(因为在不同的系统(maxOX,Linux,WIN(32/64))上运行的时间可能都不相同)我截取了几段时间来进行对比. 1.缓冲字符流B

java io 输入输出流

数据流分类:流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据.因此Java中的流分为两种: 1) 字节流:数据流中最小的数据单元是字节 2) 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节. http://blog.csdn.net/hguisu/article/details/7418161

Java - io输入输出流 --转换流

转换流  转换输出流 OutputStreamWriter: 说明: /* * OutputStreamWriter 这个类的作用 * 就是指定输出流的编码格式 * 这个类的构造方法 需要传递 一个输出流的对象 * FileOutputStream fos = new FileOutputStream("e:gu.txt"); * OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8"); * * *

Java IO输入输出流 FileWriter 字符流

字节缓冲流 //为什么要使用包装流,使用包装流是为了提高读写操作的性能. public class Packing_flowDemo { public static void main(String[] args) throws Exception { File file = new File("file/packing_flow.txt"); //包装流的写法,缓冲区内存大小.1024*8=8192 (byte) // BufferedOutputStream packing = n

java IO输入输出流实现文本复制

IO输入输出流——Java面向对象基础(29)

一.概念 IO(输入输出流) InputStream 输入流 OutputStream 输出流   输入输出流广义上就是物理存储介质.设备.容器数据的传输过程.   Java中提供一个强大的api操作IO,java.io包 二.常见的File类 File常常用于操作系统文件或目录,其中常用的方法务必掌握. File file = new File("填写文件|文件目录的路径"); createNewFile()  创建文件 delete()   删除文件或目录 exists()  判断

java的输入输出流(一)

java中i/o流是java中核心的一部分,以前学过,但是理解不够深入,渐渐的也就忘了,现在在从新学习下java的io处理,写下我学习的笔记,便于记忆,和总结归纳: 本文原创,转载请注明:http://blog.csdn.net/j903829182/article/details/38407723 1.java.io包中定义了多个流类型(类或抽象类)来实现输入/输出功能:可以从不同的角度进行分类: 按数据流的方向不同可以分为输入流和输出流. 按处理数据的单位不同可以分为字节流和字符流. 按照功

C++笔记(9):IO输入输出流

输入输出流 C++的输入输出流是IO系统向用户提供一个统一的接口,它隔离了具体的设备差异.包括标准输入输出流和文件流.标准输入输出流 istream是输入流类,cin就是istream类型的对象.ostream是输出流类,cout是ostream类型的对象. 在C++中允许用户重载运算符"<<"和">>",实现对象的输入和输出. 重载这二个运算符时,在对象所在的类中,将重载这二个运算符的函数说明该类的友元函数. C++在头文件fstream.