3、节点流(或文件流)
读入
- read()的理解: 返回读入的一个字符。如果达到文件末尾,返回-1
- 异常的处理:为了保证流资源定可以执行关闭操作。需要使用try-catch-finally处理
- 读入的文件定要存在, 否则就会报FileNotFoundException
/**
* 把文件下的hello.txt文件内容读入程序中,,并输出到控制台
* @throws IOException
*/
@Test
public void test2() throws IOException {
FileReader fr = null;
try {
//1 实例化File对象,指明操作的文件
File file = new File("hello.txt");
System.out.println(file.getAbsolutePath());
//2.提供具体的流
fr = new FileReader(file);
//3.数据的读入
//方式一
// int data = fr.read();
// while (data != -1){
// System.out.print((char) data);
// data = fr.read();
// }
//方式二 语法上对方式一的修改
int data;
while ((data = fr.read()) != -1){
System.out.print((char) data);
}
}catch (IOException e){
e.printStackTrace();
}
finally {
if (fr != null)
try {
//4.流的关闭
fr.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
使用read(char[] cbuf)读入数据
//read(char【】 cbuf):返回每次读入cbuf数组中的字符个数,如果达到文件末尾,返回-1;
@Test
public void test3() throws IOException {
//1 File 类的实例化
File file = new File("hello.txt");
//2 FileReader流的实例化
FileReader fr = new FileReader(file);
//3 读入的操作
//read(char【】 cbuf):返回每次读入cbuf数组中的字符个数,如果达到文件末尾,返回-1;
char[] cbuf = new char[5];
int len;
while ((len = fr.read(cbuf)) != -1){
//方式一
//错误的写法
// System.out.println("方式一错误的写法");
// for (int i = 0; i < cbuf.length; i++) {
// System.out.print((char) cbuf[i]);
// }
//正确写法
// System.out.println("方式一正确的写法");
// for (int i = 0; i < len; i++) {
// System.out.print((char) cbuf[i]);
// }
//方式二
//错误的方法
// System.out.println("方式二错误的写法");
// String str = new String(cbuf);
// System.out.print(str);
//正确的
// System.out.println("方式二正确的写法");
String str1 = new String(cbuf,0,len); //从0开始读,len为读几个
System.out.print(str1);
}
//4 资源关闭
fr.close();
}
写出
1.创建流对象,建立数据存放文件,文件可以不存在,不会报异常,会自动创建此文件
-
FileWriter(file,false)/ FileWriter(file)会对原有文件进行覆盖
-
FileWriter(file,true)会在原文件基础上追加
2.调用流对象的写入方法,将数据写入流
3.关闭流资源,并将流中的数据清空到文件中
/**
* 内存中写出数据到硬盘的文件中
*/
@Test
public void test4() throws IOException {
//读文件
File file = new File("hello1.txt");
//2 提供FileWriter对象,用于数据写出
FileWriter fw = new FileWriter(file,true);
//3 写出的操作
fw.write("i have a dream!\n");
fw.write("you need to have a dream!");
//4 流关闭
fw.close();
}
文本文件的复制
@Test
public void testFileReaderFileWriter() throws IOException {
//1 创建File实例化对象,知名
FileReader fr = null;
FileWriter fw = null;
try{
File rFile = new File("hello.txt");
File wFile = new File("hi.txt");
//2 提供FileReader FileWriter对象 读入 写入文件
fr = new FileReader(rFile);
fw = new FileWriter(wFile);
//3 操作
char[] cbuf = new char[5];
int len;
while ((len = fr.read(cbuf)) != -1){
for (int i = 0; i < len; i++) {
fw.write(cbuf[i]);
// System.out.println(len);
}
}
}catch (IOException e){
e.printStackTrace();
}
//4 关闭
finally {
try {
fr.close();
}catch (IOException e){
e.printStackTrace();
}
try {
fw.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
图片(字节)的复制
FileInputStream FileOutputStream
byte[] cbuf = new byte[5]
@Test
public void testInputStreamOutputStream() throws IOException {
//1 创建File实例化对象,知名
FileInputStream fr = null;
FileOutputStream fw = null;
try{
File rFile = new File("~A_@FP2TI(1440~WAW0NQ[P.jpg");
File wFile = new File("hi.jpg");
//2 提供FileReader FileWriter对象 读入 写入文件
fr = new FileInputStream(rFile);
fw = new FileOutputStream(wFile);
//3 操作
byte[] cbuf = new byte[5];
int len;
while ((len = fr.read(cbuf)) != -1){
for (int i = 0; i < len; i++) {
fw.write(cbuf[i]);
// System.out.println(len);
}
}
}catch (IOException e){
e.printStackTrace();
}
//4 关闭
finally {
try {
fr.close();
}catch (IOException e){
e.printStackTrace();
}
try {
fw.close();
}catch (IOException e){
e.printStackTrace();
}
}
} @Test
public void testInputStreamOutputStream() throws IOException {
//1 创建File实例化对象,知名
FileInputStream fr = null;
FileOutputStream fw = null;
try{
File rFile = new File("~A_@FP2TI(1440~WAW0NQ[P.jpg");
File wFile = new File("hi.jpg");
//2 提供FileReader FileWriter对象 读入 写入文件
fr = new FileInputStream(rFile);
fw = new FileOutputStream(wFile);
//3 操作
byte[] cbuf = new byte[5];
int len;
while ((len = fr.read(cbuf)) != -1){
for (int i = 0; i < len; i++) {
fw.write(cbuf[i]);
// System.out.println(len);
}
}
}catch (IOException e){
e.printStackTrace();
}
//4 关闭
finally {
try {
fr.close();
}catch (IOException e){
e.printStackTrace();
}
try {
fw.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
-
字节流操作字节,比如:.mp3,.avi,.rmvb,mp4,.jpg,.doc,.ppt
-
字符流操作字符,只能操作普通文本文件。最常见的文本文 件:.txt,.java,.c,.cpp 等语言的源代码。尤其注意.doc,excel,ppt这些不是文本文件。
4、缓冲流
提供流的读取、写入的速度
提高读写速度的原因:提供了一个缓冲区
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
字节缓冲流封装
public void copyBuffered(String srePath,String destPath){
FileInputStream fis = null;
FileOutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1 造文件
File srcFile = new File(srePath);
File destFile = new File(destPath);
//2 造流
//2.1 造节点流
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destFile);
//2.2造缓冲流
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//3 复制
byte[] bbuf = new byte[1024];
int len;
while ((len = bis.read(bbuf)) != -1){
// for (int i = 0; i < len; i++) {
// bos.write(bbuf[i]);
// }
bos.write(bbuf,0,len);
}
}catch (IOException e){
e.printStackTrace();
}
//4 关闭
// 关闭外层流的同时,内层了流也会自动关闭 可以省略关闭
// fis.close();
// fos.close();
finally {
if (bis != null){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null){
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void test2(){
long start = System.currentTimeMillis();
copyBuffered("~A_@FP2TI(1440~WAW0NQ[P.jpg","newBuffered");
long end = System.currentTimeMillis();
System.out.println("花费的时间为" + (end - start)); //花费的时间为2
}
字符缓存流封装
package IOTest.java; import org.junit.Test; import java.io.*; /** * @Description $ * @Param $ * @Return $ * @Author Xiao DaChen * @Date $ * @Time $ */ public class BufferedCahr { public void copyCharBuffered(String srePath,String destPath){ FileReader fr = null; FileWriter fw = null; BufferedReader br = null; BufferedWriter bw = null; try { //1 造文件 File srcFile = new File(srePath); File destFile = new File(destPath); //2 造流 //2.1 造节点流 fr = new FileReader(srcFile); fw = new FileWriter(destFile); //2.2造缓冲流 br = new BufferedReader(fr); bw = new BufferedWriter(fw); //3 复制 //方式一 char[] cbuf = new char[1024]; int len; while ((len = br.read(cbuf)) != -1){ // for (int i = 0; i < len; i++) { // bos.write(bbuf[i]); // } bw.write(cbuf,0,len); bw.flush(); } //方式二 // String data; // while ((data = br.readLine()) != null){ // bw.write(data); // bw.newLine(); // } }catch (IOException e){ e.printStackTrace(); } //4 关闭 // 关闭外层流的同时,内层了流也会自动关闭 可以省略关闭 // fis.close(); // fos.close(); finally { if (br != null){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (bw != null){ try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void test(){ long start = System.currentTimeMillis(); copyCharBuffered("hello.txt","newHello.txt"); long end = System.currentTimeMillis(); System.out.println("花费的时间为"+(end - start)); } }
缓冲流习题一_图片加密(解密的话,调换文件位置就可以了)
package IOTest.exer;
import org.junit.Test;
import java.io.*;
/**
1. 实现图片加密操作
int b= 0;
while((b = fis.read()) != -1){
fos.write(b ^ 5);
}
*/
public class BufferedExer2 {
@Test
public void test1() throws IOException {
FileInputStream fis = new FileInputStream(new File("~A_@FP2TI(1440~WAW0NQ[P.jpg"));
FileOutputStream fos = new FileOutputStream(new File("secret.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1){
for (int i = 0; i < len; i++) {
buffer[i] = (byte) (buffer[i] ^ 5);
}
fos.write(buffer,0,len);
}
fis.close();
fos.close();
}
@Test
public void test2() throws IOException {
FileInputStream fis = new FileInputStream(new File("secret.jpg"));
FileOutputStream fos = new FileOutputStream(new File("newSecret.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1){
for (int i = 0; i < len; i++) {
buffer[i] = (byte) (buffer[i] ^ 5);
}
fos.write(buffer,0,len);
}
fis.close();
fos.close();
}
}
缓冲流习题二_获取文本上每个字符出现的次数
package IOTest.exer;
import org.junit.Test;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @Description $
* @Param $
* @Return $
* @Author Xiao DaChen
* @Date $
* @Time $
*/
public class WordsCountSelf {
@Test
public void test(){
FileReader fr = null;
BufferedWriter bw = null;
try {
Map<Character,Integer> map = new HashMap<>();
fr = new FileReader(new File("newHello.txt"));
int c = 0;
while ((c = fr.read()) != -1){
char ch = (char) c;
//在这每次都会创建一个新的map,所以结果是最后一个额句号
//result: 。=1
// Map<Character,Integer> map = new HashMap<>();
if (map.get(ch) == null){
map.put(ch,1);
}else {
map.put(ch,map.get(ch) + 1);
}
bw = new BufferedWriter(new FileWriter("countSelf.txt"));
Set<Map.Entry<Character,Integer>> entrySet = map.entrySet();
for (Map.Entry<Character,Integer> entry : entrySet){
switch (entry.getKey()){
case ' ':
bw.write("空格=" + entry.getValue());
break;
case '\n':
bw.write("换行=" + entry.getValue());
break;
case '\r':
bw.write("回车=" + entry.getValue());
break;
case '\t':
bw.write("tap键="+entry.getValue());
break;
default:
bw.write(entry.getKey() + "=" +entry.getValue());
}bw.newLine();
}
}
}catch (IOException e){
e.printStackTrace();
}finally {
if (fr != null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bw != null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
5、转换流
1.将char转换为byte
InputStreamReader:实现将字节的输入流按指定字符集转换为字符的输入流,解码
OutputStreamWriter:实现将字符的输出流按指定字符集转换为字节的输出流,编码
2.作用:
提供字节流与字符流之间的转换
3. 解码:字节、字节数组 ---》字符数组,字符串
编码:字符数组‘字符串 ---》 字节、字节数组’
6、标准输入、输出流
package IOTest.java;
import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class SystemTest {
public static void main(String[] args) {
InputStreamReader isr = null;
BufferedReader br = null;
try{
isr = new InputStreamReader(System.in);
br = new BufferedReader(isr);
String data;
while (true) {
System.out.println("请输入字符串");
data = br.readLine();
if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)) {
break;
}
String str = data.toUpperCase();
System.out.println(str);
}
}catch (IOException e){
e.printStackTrace();
}finally {
if (br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
7、打印流
package IOTest.java;
import org.junit.Test;
import java.io.*;
public class OtherStreamTest {
@Test
public void test(){
PrintStream ps = null;
try {
FileOutputStream fos = new FileOutputStream(new File("D:\\AbandonIT\\Idea\\iotest\\test.txt"));
//创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
ps = new PrintStream(fos,true);
if (ps != null){
System.setOut(ps);
}
for (int i = 0; i < 255; i++) {
System.out.print((char) i);
if (i % 50 == 0){
System.out.println();
}
}
}catch (IOException e){
e.printStackTrace();
}finally {
if (ps != null){
ps.close();
}
}
}
}
8、数据流
用于读取或写出基本数据类型的变量或者字符
先写出去在读
练习:将内存中的字符串,基本数据类型的变量写出到文件中。
package IOTest.java;
import org.junit.Test;
import java.io.*;
public class DataStreamTest {
@Test
public void test1() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeUTF("刘志和");
dos.flush();
dos.writeInt(22);
dos.flush();
dos.writeBoolean(true);
dos.flush();
dos.close();
}
@Test
public void test2() throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
String name = dis.readUTF();
int age = dis.readInt();
boolean gender = dis.readBoolean();
System.out.println("name:"+name+",age:"+age+",genderMan:"+gender);
}
}
9、对象流
重点:序列化机制
package guigu.java;
import org.junit.Test;
import java.io.*;
/**
1. objectInputSrram objectOuputStream
*/
public class ObjectIntputStreamTest {
/**
序列化过程:将内存中的java对象保存在磁盘中或通过网络传播出去
使用ObjectOutputStream实现
*/
@Test
public void test1() throws IOException {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("object.txt"));
oos.writeObject(new String("天天开心"));
oos.flush();
}catch (IOException e){
e.printStackTrace();
}finally {
if (oos != null){
oos.close();
}
}
}
/**
反序列化过程:将磁盘文件中的对象还原成内存中的一个java对象
使用ObjectOutputStream实现
*/
@Test
public void test2() throws IOException {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("object.txt"));
Object obj = ois.readObject();
String str = (String) obj;
System.out.println(str);
}catch (IOException | ClassNotFoundException e){
e.printStackTrace();
}finally {
if (ois != null){
ois.close();
}
}
}
}
添加person对象
oos.writeObject(new Person("王守仁",22);
java.io.NotSerializableException: guigu.java.Person
1. objectInputSrram 反序列化 / objectOuputStream 序列化 2.满足条件,支持序列化机制: 有接口 Serializable(标识接口,内部没有实现方法) / Externalizable 需要当前类提供一个全局变量 public static long serialVersionUID = 45432543543L; 保证内部所以属性也必须是可序列化的 new Person(xx,xx,new Account(xx,xx)) Account也得是可序列化的 static transient 修饰的成员变量无法序列化,传入的是null
10、随机存取文件流
ReandomAccessFile类
1.RandomAccessFile 直接继承与java.lang.Object类,实现了DataInput和DataOutput接口 2.RandomAccessFile 既可以作为一个输入流,也可以作为一个输出流 3.如果文本文件存在,此类作为输出流操作,对原有文件覆该;不存在就是自动创建 4.可以通过相关操作,达到插入数据的效果
public class RandomAccessFileTest {
@Test
public void test1() throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("~A_@FP2TI(1440~WAW0NQ[P.jpg"),"r");
RandomAccessFile raf2 =new RandomAccessFile(new File("~A_@FP2TI(1440~WAW0NQ[P1.jpg"),"rw");
byte[] buffer =new byte[1024];
int len;
while ((len = raf2.read(buffer)) != -1){
raf2.read(buffer,0,len);
}
raf2.close();
raf.close();
}
@Test
public void test2() throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("hello.txt"),"rw");
raf.seek(raf.length());//指针调到角标为3的位置
raf.write("xyz".getBytes());
}
/**
插入数据的效果
*/
@Test
public void test3() throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("hello.txt"),"rw");
raf.seek(3);//指针调到角标为3的位置
//保存指针后面的所有数据到StringBuilder中
StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());
byte[] buffer= new byte[20];
int len;
while ((len = raf.read(buffer)) != -1){
builder.append(new String(buffer,0,len));
}
//调回指针,写入xyz
raf.seek(3);
raf.write("xyz".getBytes());
raf.close();
//写入之前存入StringBuilder的数据
raf.write(builder.toString().getBytes());
}
}