-----------android培训、java培训、java学习型技术博客、期待与您交流!-----------
一.IO流
1.概念
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的类都在IO包中
流按流向分为两种:输入流,输出流。
流按操作类型分为两种:字节流与字符流。字节流可以操作任何数据,字符流只能操作纯字符数据,比较方便。
2.IO流常用父类
字节流的抽象父类:
InputStream,OutputStream
字符流的抽象父类:
Reader, Writer
3.IO程序书写
使用前,导入IO包中的类
使用时,进行IO异常处理
使用后,释放资源
二.字节流
1.读取文件
创建FileInputStream对象,指定一个文件.文件必须存在,不存在则会抛出FileNotFoundException
使用read()方法可以从文件中读取一个字节.如果读取到文件末尾会读到-1
读取结束后需要释放资源,调用close()方法关闭输入流
2.写出文件
创建FileOutputStream对象,指定一个文件.文件不存在会创建新文件,存在则清空原内容.如果需要追加,在构造函数中传入true.
使用write()方法可以向文件写出一个字节.
写出结束后同样需要调用close()
3.拷贝文件
可以从文件中逐个字节读取,逐个字节写出,但这样做效率非常低
我们可以定义一个数组作为缓冲区,一次读取多个字节装入数组,然后再一次性把数组中的字节写出1byte = 8bit
4.常用方法
InputStream:
read()读取一个字节
read(byte[])读取若干(数组长度)字节
available()获取可读的字节数
close()关闭流,释放资源
OutputStream:
write(int)写出一个字节
write(byte[])写出数组中的所有字节
write(byte[],start,len);
close()关闭流,释放资源
5.BufferedInputStream
BufferedInputStream内置了一个缓冲区(数组)
从BufferedInputStream中读取一个字节时
BufferedInputStream会一次性从文件中读取8192个,存在缓冲区中,返回给程序一个
程序再次读取时,就不用找文件了,直接从缓冲区中获取
直到缓冲区中所有的都被使用过,才重新从文件中读取8192个
6.BufferedOutputStream
BufferedOutputStream也内置了一个缓冲区(数组)
程序向流中写出字节时,不会直接写到文件,先写到缓冲区中
直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里
三、
1.四种拷贝文件方法
* a.使用FileInputStream和FileOutputStream,逐个字节拷贝
* b.使用FileInputStream和FileOutputStream,定义一个大数组(length等于文件大小),一次性拷贝
***** c.使用FileInputStream和FileOutputStream,定义一个小数组(例如1024),多次拷贝
***** d.使用BufferedInputStream和BufferedOutputStream内置的缓冲区,逐个字节拷贝
2.标准化IO流操作的代码
*** a.finally嵌套
*** b.try close
四.练习
1,copy文件
package com.heima.bij.io.test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo_Copy_Method {
/**
* 1,copy文件
*/
public static void main(String[] args) throws IOException {
//demo1();
//demo2();
//demo3();
//demo4();
FileInputStream fis = new FileInputStream("Beyond - 海阔天空.mp3");//创建字节流读取对象
FileOutputStream fos = new FileOutputStream("copy.mp3");//创建字节流写出对象
byte[] arr = new byte[fis.available()];
fis.read(arr);
fos.write(arr);
fis.close();
fos.close();
}
public static void demo4() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("Beyond - 海阔天空.mp3");//创建字节流读取对象
FileOutputStream fos = new FileOutputStream("copy.mp3");//创建字节流写出对象
BufferedInputStream bis = new BufferedInputStream(fis);//将字节流对象包装
BufferedOutputStream bos = new BufferedOutputStream(fos);//将字节流对象包装
int b;
while((b = bis.read()) != -1) { //从输入流缓冲区的字节数组读
bos.write(b); //写到输出流的缓冲区字节数组
}
bis.close();
bos.close();
}
public static void demo3() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("Beyond - 海阔天空.mp3"); //创建字节流读取对象
FileOutputStream fos = new FileOutputStream("copy.mp3");//创建字节流写对象
int len; //记录读取的有效的字节个数
byte[] arr = new byte[1024]; //创建字节数组
while((len = fis.read(arr)) != -1) { //将数据读取到字节数组中
fos.write(arr, 0, len); //将字节数组写出去,按照len写出有效的字节个数
}
fis.close();
fos.close();
}
public static void demo2() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("aaa.txt");
FileOutputStream fos = new FileOutputStream("bbb.txt");
int len; //记录读取的有效的字节个数
byte[] arr = new byte[1024];
while((len = fis.read(arr)) != -1) {
//fos.write(arr);
fos.write(arr, 0, len);
}
fis.close();
fos.close();
}
public static void demo1() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("aaa.txt");
byte[] arr = new byte[2];
int len1 = fis.read(arr);
for (byte b : arr) {
System.out.println(b);//97 98
}
System.out.println("---------------------");
int len2 = fis.read(arr);
for (byte b : arr) {
System.out.println(b);//99 98
}
System.out.println("-------------------");
int len3 = fis.read(arr);
int len4 = fis.read(arr);
System.out.println(len1);
System.out.println(len2);
System.out.println(len3);
System.out.println(len4);
fis.close();
}
}
2,给图片加密
package com.heima.bij.io.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test_pagejiami {
/**
* 2,给图片加密
* 思路:加密即可以通过异或一个密码,解密只需要再异或一次即可
*/
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("1.jpg");
FileOutputStream fos = new FileOutputStream("2.jpg");
//解密只需要再将图标异或一次即可
//FileInputStream fis = new FileInputStream("2.jpg");
//FileOutputStream fos = new FileOutputStream("3.jpg");
int b;
while((b=fis.read())!=-1) {
fos.write(b ^ 123456);//通过异或进行加密
}
fis.close();
fos.close();
}
}
3.从键盘输入接收一个文件路径,把该文件的内容拷贝到工程中
package com.heima.bij.io.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Test_lujing {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个文件路径");
String dir = sc.nextLine();//把路径存放到dir变量中
int index = dir.lastIndexOf('\\');//单斜线是专业字符,所以需要用双;读取最右边的\
String name = dir.substring(index+1);//通过下标+1获取文件名
FileInputStream fis = new FileInputStream(dir); //创建文件的读取对象
FileOutputStream fos = new FileOutputStream(name);//创建写文件的对象
int len;
byte[] arr = new byte[1024];//定义缓冲区
while((len=fis.read(arr))!= -1) {//将文件读到缓存区去
fos.write(arr,0,len); //写出缓冲区
}
fis.close();
fos.close();
sc.close();//sc也需要关闭资源
}
}
4.从键盘接收输入,把键盘输入的数据写到文件,直到输入quit时退出
package com.heima.bij.io.test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Io_copy {
/**
* 4,将键盘录入的数据拷贝到当前项目下的text.txt文件中,键盘录入数据当遇到quit时就退出
*/
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
FileOutputStream fos = new FileOutputStream("text.txt",true);
System.out.println("请输入:");
while(true) {
String line = sc.nextLine();
if(line.equals("quit"))
break;
fos.write(line.getBytes()); //将键盘录入的字符串转换为字节数组写出去
//fos.write('\r');
//fos.write('\n');
fos.write("\r\n".getBytes()); //写出回车换行符号
}
sc.close();
fos.close();
}
}
附加题:约瑟夫环
package com.heima.bij.io.test;
import java.util.LinkedList;
import java.util.List;
/**
* 附加题:约瑟夫环
*/
public class Io_yuesefuhuan {
public static void main(String[] args) {
int lucklyNum = getLucklyNum(8);
System.out.println(lucklyNum);
}
//定义getLuckyNum方法
public static int getLucklyNum(int num) {
List<Integer> list = new LinkedList<>();
//将num存入集合中
for(int i = 1; i <= num; i++) {
list.add(i);
}
int count = 1; //查数
for(int i = 0; list.size() != 1 ; i++) { //遍历集合,只要集合中的元素不为1,就不断循环
if(i == list.size()) { //当i自增到了集合中元素的个数时
i = 0; //就将i重新置为0;count还是在自加,比如此时,归零,对应count=9
}
if(count % 3 == 0) { //只要查到了3的倍数就从集合中杀人
list.remove(i--); //删除的时候要索引--
}
count++; //查数递增
}
return list.get(0); //最后集合中只有一个元素就是哪个幸运的数
}
}
控制台结果:
7
关键代码分析:remove(i--),为何要i--?
答:删除3后,后面的数会自动补上,即4补到3的位置上,5补到4位置上,然而此时索引指向的是4原来的位置,这样就会漏掉一个4,所以要remove(i)后再将i--,画图分析如下
使用迭代器也可以实现约瑟夫环
代码如下:
package com.heima.bij.io.test;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* 附加题:约瑟夫环
* 分析:使用迭代其也可以实现约瑟夫环
*/
public class Io_yuesefuhuan_iterator {
public static void main(String[] args) {
int counter = 1;
List<Integer> list = new LinkedList<>();
for(int i = 1; i <= 8; i++)
list.add(i);
System.out.println(list);
while(true) {
Iterator<Integer> it = list.iterator();
if(list.size() == 1)
break;
while(it.hasNext()) {
Integer i = it.next();
if(counter++ % 3 == 0){
it.remove();
System.out.print(i + " ");
}
}
}
System.out.println("\n" + list);
}
}
控制台结果:
[1, 2, 3, 4, 5, 6, 7, 8]
3 6 1 5 2 8 4
[7]