IO流
I: input : 输入
O: output: 输出
-
文件的本质
存储都是二进制的数据. 我们能够看到数据的具体形态,都是因为各自的软件帮我们做了解码的工作
2.字节和字符的区别:
字节是存储容量的基本单位,1字节=8个二进制位. 所有类型的文件都可以用字节形式打开
字符是指字母,数字,汉子和各种符号. 只能去表示文本文档
一个字符在计算机中用若干个字节的二进制数表示
char 等于2个byte
gbk: 中文:2个字节 英文/数字: 1个字节
utf–8: 中文:三个字节 英文/数字: 1个字节
计算机中所有的数据可以使用字节表示 但是只有纯文本文件才能使用字符表示
凡是打开看的懂得一般使用字符流去操作
如果打开看不懂的那就使用字节流去操作
字符流能操作的文件 字节流一定能操作
字节流能操作的文件 字符流肯定可以 但是 会出现精度丢失
凡是多媒体文件 一般用字节流去操作
凡是文本文档 一般用字符流去操作
3.读写和输入输出的关系
输入: 读
输出: 写
读进来,写出去
4.IO流的分类
从流向上划分:
输入流: input
输出流: output
从处理的单位上:
字节流: 以字节为单位进行处理 (任何文件)
字符流: 以字符为单位进行处理 (纯文本文件)
两两组合得到四个基类
字节输入流: inputstream
字节输出流: outputstream
字符输入流: Reader
字符输出流: Writer
凡是以InputStream 结尾的,都是属于字节输入流
凡是以outputStream结尾的,都是属于字节输出流
凡是以Reader结尾的,都是属于字符输入流
凡是以Writer结尾的,都是属于字符输出流
IO流在java里面有称之为管道流:
-
FileOutputStream/FileInputStream 用法
FileOutputStream : 文件字节输出流,以字节为单位向文件中写数据
FileOutputStream(File file)
FileOutputStream(String path)
public void write(int b) 写一个字节
public void write(byte[] b) 写一个byte数组
public void write(byte[] b,int off,int len) 写一个数组,从off开始,len个长度
public class IODemo1 { public static void main(String[] args) { FileOutputStream fos = null; try { // fos = new FileOutputStream(new File("G://a.txt"));//底层其实是做了一个判断 判断你这个路径是否存在 如果不存在就创建 // 如果存在 就直接指向 fos = new FileOutputStream("G://a.txt"); fos.write(98); fos.write(99); String s = "helloworld"; fos.write(s.getBytes()); String s1 = "我爱中国,我爱java"; fos.write(s1.getBytes(),0,3); } catch (IOException e) { e.printStackTrace(); }finally { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
JDK7: 自动关流:
把流的定义语句放到try()中,这样当程序结束后,就可以自动帮我们关流了
在try() 中只能定义流的定义语句 (实现AutoCloseable接口)
FileOutputStream(String path,boolean append)
append: 是否追加:
true: 如果源文件已存在,且里面有内容,则写入的数据会在原来文件的内容后面继续写
false; 如果源文件已存在,且里面有内容,会先将源文件中的内容清空,再写
文件输入流
FileInputStream:
public int read() 一次只能读一个字节
public int read(byte[] b) 一次能读一个数组个字节
package com._51doit.demo3;
import java.io.FileOutputStream;
import java.io.IOException;
//FileOutputStream(String path,boolean append) 追加写入
public class IODemo2 {
public static void main(String[] args) {
// jdk1.7以后 如何实现自动关流操作
try (FileOutputStream fos = new FileOutputStream("G://a.txt",true)){
String s = "我爱helloworld";
String s1 = "我爱java";
fos.write(s.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com._51doit.demo3;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/*
*
* 文件输入流
* FileInputStream:
* public int read() 一次只能读一个字节
public int read(byte[] b) 一次能读一个数组个字节
*
*/
public class IODemo3 {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("G://a.txt")){
// int a = fis.read();
// int b = fis.read();
// int c = fis.read();
//
// byte[] by = {(byte)a,(byte)b,(byte)c};
//
//
// String s = new String(by);
//
// System.out.println(s);
byte[] b = new byte[1024];
fis.read(b);
System.out.println(new String(b));
} catch (IOException e) {
e.printStackTrace();
}
}
}
6.文件字节输出流用法
构造方法:
FileOutputStream(String path); //路径代表写出到哪个文件中
File OutputStream(File file);
FileOutputStream(String path,boolean append);//append: true: 如果源文件有内容,在内容后追加
File OutputStream(File file,boolean append);
成员方法:
write(int a);
write(byte[] bs);
write(byte[]bs,int offset,int len);
ackage Demo1;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
public class Text1 {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("C:\\b.jpg");
FileInputStream fis = new FileInputStream("D:\\a.jpg");
long l1 = System.currentTimeMillis();
byte[]by=new byte[1024];
int len;
while ((len=fis.read(by))!=-1) {
fos.write(by, 0, len);
}
long l2 = System.currentTimeMillis();
System.out.println("复制成功");
System.out.println("所用时间为"+(l2-l1));
}
}
7.文件字节输入流用法
构造方法:
FileInputStream(String path);//代表从哪个文件中读取数据
FileInputStream(File file);
成员方法:
public int read() 每次读取一个字节,并返回
public int read(byte[] b) 每次读取一个数组长度的字节,数组存到了数组中,返回真正读取回来的长度
package Demo1;
// 读取的速度: 高效流读取一个字符>普通流读取一个字符>高效流读取一个字节>普通流读取一个字节
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class Text2 {
public static void main(String[] args) throws Exception {
//copyFile();
// copyFile2();
// copyFile3();
copyFile4();
}
//这是普通流读一个字节
private static void copyFile4() throws Exception {
FileOutputStream fos = new FileOutputStream("F:\\b.avi");
FileInputStream fis = new FileInputStream("F:\\a.wmv");
long c1=System.currentTimeMillis();
int len;
while ((len=fis.read()) != -1) {
fos.write(len);
}
long c2=System.currentTimeMillis();
System.out.println("这是普通流读一个字节"+(c2-c1));
fis.close();
fos.close();
}
//这是普通流读一个数组
private static void copyFile3() throws Exception {
FileOutputStream fos = new FileOutputStream("F:\\b.avi");
FileInputStream fis = new FileInputStream("F:\\a.wmv");
long l1 = System.currentTimeMillis();
byte[]by=new byte[1024];
int len;
while ((len=fis.read(by))!=-1) {
fos.write(by, 0, len);
}
long l2 = System.currentTimeMillis();
System.out.println("这是普通流读一个数组"+(l2-l1));
fis.close();
fos.close();
}
//注释高效流读一个数组
private static void copyFile2() throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\a.wmv"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\b.avi"));
long c1=System.currentTimeMillis();
byte[]b= new byte[1024];
int len;
while ((len=bis.read(b)) != -1) {
bos.write(b, 0, len);;
}
long c2=System.currentTimeMillis();
System.out.println("这是高效流读一个数组"+(c2-c1));
bis.close();
bos.close();
}
//这是高效流读一个字节
private static void copyFile() throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\a.wmv"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\b.avi"));
long c1=System.currentTimeMillis();
int len;
while ((len=bis.read()) != -1) {
bos.write(len);
}
long c2=System.currentTimeMillis();
System.out.println("这是高效流读一个字节"+(c2-c1));
bis.close();
bos.close();
}
}
在使用普通字节流的时候,都会产生大量的IO操作
每一次读写都是直接操作的磁盘 计算机中 读写的速度最慢的就是磁盘
缓冲字节流输出流
bufferedoutputStream(out putStream) 包装模式
flush:缓冲输出流中特有的方法 将缓冲区的内容写到文件中
close:会先调用flush方法,在关流
public class Demo4 {
public static void main(String[] args) throws Exception {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("G://a.txt"));
bos.write(97);
bos.write(98);
bos.write(99);
bos.write(100);
bos.write(101);
String s = "你是个笨蛋";
bos.write(s.getBytes());
byte[] by = new byte[1024];
bos.write(by, 0, s.getBytes().length);
// 刷新缓冲区 清空缓冲区 并将缓冲区中的数据写入到磁盘上
// bos.flush();
bos.close();//关闭流 在关闭流之前 他会先去将缓冲区中所有的数据刷新到文件中 然后再关流
}
}
缓冲字节输入流
bufferedinputStream(input Stream)
bufferedinputstream(inputstream,int size) size:缓冲区大小
默认8K
转换符(字符流)
字符流:字节流+编码
编码: 把文字转成二进制
解码: 把二进制转换成文件
字符输出流
构造方法:
public outputstreamwriter(outputstream out)
public outputstreamwriter(outputstreamout,string charsetname)
成员方法
public void write(int c)
public void write(char[ ]cbuf)
public void write(char[ ]cubf,int off,int len)
public void write(string str)
public void write(string str,int off,int len)
public class Demo1 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("G://a.txt");
// fos.write('h');
//
// String s = "我爱java";
// fos.write(s.getBytes());
// System.out.println(fis.read());
// int a = fis.read();
// int b = fis.read();
// int c = fis.read();
//
// byte[] by = {(byte)a,(byte)b,(byte)c};
//
// System.out.println(new String(by));
byte[] b2 = new byte[1024];
// int len = fis.read(b2);
// System.out.println(new String(b2));
// System.out.println(new String(b2, 0, len));
int len = fis.read(b2);
System.out.println(new String(b2,0,len));
}
}
ublic class Demo7 {
public static void main(String[] args) throws Exception {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("G://a.txt"));
osw.write(97);
char[] ch = {'A','B','C'};
osw.write(ch);
osw.write(ch,0,1);
osw.write("你们别睡觉了 再睡几天就没课了 下个班见?");
osw.flush();
}
}
字符输入流
构造方法
public InputStreamReader(InputStream in)
public InputStreamReader(InputStream in,String charsetName)
成员方法:
public int read()
public int read(char[] cbuf)
package com._51doit.demo;
import java.io.FileInputStream;
import java.io.InputStreamReader;
/*
* ## 字符输入流
> **构造方法**
>
> public InputStreamReader(InputStream in)
>
> public InputStreamReader(InputStream in,String charsetName)
>
>
>
> **成员方法:**
>
> public int read()
>
> public int read(char[] cbuf)
*
*
* 使用转换流去分别复制一个文本文件 一张图片 然后对比一下 会出现什么情况
*
*/
public class Demo8 {
public static void main(String[] args) throws Exception {
InputStreamReader isr = new InputStreamReader(new FileInputStream("G://a.txt"));
System.out.println(isr.read());
char[] ch = new char[1024];
int len = isr.read(ch);
System.out.println(new String(ch, 0, len));
}
}
简化流(字符流)
不能指定编码,也不能把字节转成字符流
File Reader/File Writer
缓冲字符流
bufferedwriter
void new Line()
buffered Reader string readLine()
public class Demo11 {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("Test1.txt");
FileWriter fw = new FileWriter("copyTest.java");
char[] ch = new char[1024];
int len = 0;
while ((len = fr.read(ch)) != -1) {
fw.write(ch);
}
fw.close();
fr.close();
}
}
package com._51doit.demo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
*
* # 缓冲字符流
读和写
> **BufferedWriter**
>
> void newLine() //就相当于一个换行符 他能根据你的当前系统以及运行环境等等 生成一个适用的换行符
>
> **BufferedReader**
>
> String readLine() //一读一行
*
*/
public class Demo12 {
public static void main(String[] args) throws Exception {
BufferedWriter bw = new BufferedWriter(new FileWriter("Test1.txt"));
BufferedReader br = new BufferedReader(new FileReader("copyTest.java"));
bw.write("我爱学习,但是我更爱java");
bw.newLine();
bw.write("你爱学习吗?不,我爱java");
bw.flush();
String line = br.readLine();
String line1 = br.readLine();
System.out.println(line);
System.out.println(line1);
}
}
package com._51doit.demo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class Demo13 {
public static void main(String[] args) throws Exception {
/*
* 到底flush该在什么时候用
* 文件小的时候 你关流刷新就行
* 但是文件越来越大 如果你一直往缓冲区里面写东西
* 会对缓冲区形成很大的压力
*
* 所有 在读取大文件的时候 你们要时时进行刷新
*
*/
BufferedReader br = new BufferedReader(new FileReader("copyTest.java"));
BufferedWriter bw = new BufferedWriter(new FileWriter("Test1.java"));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.flush();
bw.newLine();
}
bw.close();
br.close();
}
}
序列化和对象流
序列化: 把对象转换成二进制
反序列化:把二进制转换成对象
持久化:把内存数据存储到磁盘上(一般数据库)
实现序列化的步骤:
1. 让类实现 serializable 接口
2. 使用objectoutstream写数据:调用writeobject
3. 使用objectinputstream 读数据:调用read object
File inputstream/Fileoutputstream 文件字节流
Bufferedinputstream/Bufferedoutputstream 缓冲字节流 flush
inputstreamreader/outputstreamwriter 转换流 把字节转成字符流,能够指定编码
Filereader/Filewriter 简化流 不能指定编码
bufferedreader/bufferedwriter 缓冲字符流 newLine/readline
object inputstream/object outputstream 对象流 序列化/反序列化
serzaliazable write object/read object
package Demo1;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
public class text7 {
public static void main(String[] args) throws Exception {
ArrayList<String> al = new ArrayList<String>();
al.add("helloworld");
al.add("java");
al.add("pothon");
al.add("c++");
al.add("c#");
al.add("bigdata");
BufferedWriter bw = new BufferedWriter(new FileWriter("data.java"));
BufferedReader br = new BufferedReader(new FileReader("data.java"));
ArrayList<String> al2 = new ArrayList<String>();
for (String str : al) {
bw.write(str);
bw.newLine();
bw.flush();
}
bw.close();
String line;
while ((line=br.readLine())!= null) {
al2.add(line);
}
System.out.println(al2);
}
}