IO流用来处理设备之间的数据传输。Java对数据的操作是通过流的方式。Java用于操作流的对象都在IO包中。流按照流向分为输入流和输出流。按照操作的数据类型分为字节流和字符流。
6.4 字节流
6.4.1 字节输出流
1.操作步骤
1)创建字节输出流对象
2)写入数据(调用write方法)
3)释放资源
2.write方法
public void write(int b):写一个字节
public void write(byte[] b):写一个字节数组
public void write(byte[] b,int off,int len):写一个字节数组的一部分
示例1:
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo2 {
public static void main(String[] args) throws IOException {
// 创建字节流输出对象
FileOutputStream fos = new FileOutputStream("fos2.txt");
// 写入数据
// public void write(int b):写一个字节
fos.write(97); // 想要显示出字母a,其实就是写入字母a所对应的二进制数,换算成十进制数就是97
fos.write(57); // 想要显示出数字9,其实就是写入数字9所对应的二进制数,换算成十进制数就是57
fos.write(55);// 想要显示出数字7,其实就是写入数字7所对应的二进制数,换算成十进制数就是55
fos.write('\r');// 换行
fos.write('\n');// 换行
// public void write(byte[] b):写一个字节数组
byte[] bys = { 97, 98, 99, 100, 101 };
byte[] bys2 = { '\r', '\n' };
fos.write(bys);
fos.write(bys2);// 换行
// public void write(byte[] b,int off,int len):写一个字节数组的一部分
fos.write(bys, 0, 3);
// 释放资源
fos.close();
}
}
运行结果:
示例2:实现数据的追加写入
创建字节流输出对象时选择有两个参数的构造方法。例如:public FileOutputStream(File file,boolean append)
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 如何实现数据的换行?
* 为什么现在没有换行呢?因为你只写了字节数据,并没有写入换行符号。
* 如何实现呢?写入换行符号即可呗。
* 刚才我们看到了有写文本文件打开是可以的,通过windows自带的那个不行,为什么呢?
* 因为不同的系统针对不同的换行符号识别是不一样的?
* windows:\r\n
* linux:\n
* Mac:\r
* 而一些常见的个高级记事本,是可以识别任意换行符号的。
*
* 如何实现数据的追加写入?
* 用构造方法带第二个参数是true的情况即可
*/
public class FileOutputStreamDemo3 {
public static void main(String[] args) throws IOException {
// 创建字符流对象
FileOutputStream fos = new FileOutputStream("fos3.txt",true);
// 写入数据
fos.write("写入数据:".getBytes());
// 换行
fos.write("\r\n".getBytes());
for (int x = 0; x < 5; x++) {
fos.write(("hello" + x).getBytes());
fos.write("\t".getBytes());
}
// 换行
fos.write("\r\n".getBytes());
// 释放资源
fos.close();
}
}
运行两次后结果:
示例3:加入try异常处理后的字节输出流操作
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo4 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
//fos = new FileOutputStream("z:\\fos4.txt");
fos = new FileOutputStream("fos4.txt");
fos.write("我".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(Exception e){
e.printStackTrace();
}finally{
//如果fos不是null,才需要close();
if(fos!=null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
运行结果:
思考:FileOutputStream fos = new FileOutputStream("fos.txt");这条语句一共做了几件事情呢?
1)调用系统功能去创建文件fos.txt
2)创建FileOutputStream对象fos
3)把对象fos指向fos.txt这个文件
6.4.2 字节输入流
1.操作步骤:
1)创建字节输入流对象
2)调用read方法读取数据,并且把数据显示在控制台
3)释放资源
2.read方法
int read():一次读取一个字节
int read(byte[] b):一次读取一个字节数组。返回值是实际读取的字节个数。
示例1:一次读取一个字节
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
// FileInputStream(String name)
FileInputStream fis = new FileInputStream("fis.txt");
//调用read方法读取数据,并且把数据显示在控制台
int by = 0;
//读取、赋值、判断
while((by=fis.read())!=-1){
System.out.print((char)by);
}
//释放资源
fis.close();
}
}
运行结果:
第三行打印出的???ú是什么意思呢?查看了下fis.txt源文件,发现fis.txt第三行是“中国”两个汉字,由于中文在计算机中存贮时使用两个字节,第一个字节肯定是负数,第二个字节可正可负。以“国”为例,因为read()方法每次读取一个字节,所以读取“国”字的时候,会先读取“国”字的第一个字节,然后将其转换成字符类型, 因为第一个负数没有对应的字符,所以打印出“?”,第二个数对应“ú”,所以打印出“ú”。
示例2:一次读取一个字节数组
public class FileInputStreamDemo2 {
public static void main(String[] args) throws IOException {
// 创建字节输入对象流
FileInputStream fis = new FileInputStream("fis2.txt");
//读取数据
//数组的长度一般是1024或1024的整数倍
byte[] bys = new byte[1024];
int len = 0;
while((len = fis.read(bys))!=-1){
System.out.println(new String(bys,0,len));
}
// 释放资源
fis.close();
}
}
运行结果:
6.4.3 字节流缓冲区
缓冲区的出现提高了对数据的读写效率。
注意:缓冲区必须要结合流才能使用。
1.BufferedOutputStream
示例:
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferedOutputStreamDemo {
public static void main(String[] args) throws IOException {
// 构造方法:BufferedOutputStream(OutputStream out)
// 创建一个BufferedOutputStream对象bos,并将bos和新建的FileOutputStream对象相关联
</span> BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("bos.txt"));
// 写数据
bos.write("hello".getBytes());
// 关闭资源
bos.close();
}
}
运行结果:
2.BufferedInputStream
示例:
public class BufferedInputStreamDemo {
public static void main(String[] args) throws IOException{
// 构造方法:BufferedInputStream(InputStream in)
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bos.txt"));
//读取数据
byte[] bys = new byte[1024];
int len = 0;
while((len = bis.read(bys))!=-1){
System.out.println(new String(bys,0,len));
}
}
}
运行结果:
6.4.4 字节流的练习题
练习1:使用字节流复制文本的4种方式
需求:使用4种方式把C:\Users\Public\Music\Sample Music\Kalimba.mp3复制到当前项目目录下的copy.mp3中,并计算所用时间
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyMp3Demo {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
// mtehod1("C:\\Users\\Public\\Music\\Sample Music\\Kalimba.mp3","copy1.mp3");
// mtehod2("C:\\Users\\Public\\Music\\Sample Music\\Kalimba.mp3","copy2.mp3");
// mtehod3("C:\\Users\\Public\\Music\\Sample Music\\Kalimba.mp3","copy3.mp3");
mtehod4("C:\\Users\\Public\\Music\\Sample Music\\Kalimba.mp3","copy4.mp3");
long end = System.currentTimeMillis();
System.out.println("共耗时:" + (end - start) + "毫秒");
}
// 基本字节流一次读写一个字节
public static void mtehod1(String srcString, String destString)
throws IOException {
// 封装数据源
FileInputStream fis = new FileInputStream(srcString);
// 封装目的地
FileOutputStream fos = new FileOutputStream(destString);
// 复制数据
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}
// 关闭资源
fos.close();
fis.close();
}
// 基本字节流一次读写一个数组
public static void mtehod2(String srcString, String destString)
throws IOException {
// 封装数据源
FileInputStream fis = new FileInputStream(srcString);
// 封装目的地
FileOutputStream fos = new FileOutputStream(destString);
// 复制数据
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
// 关闭资源
fos.close();
fis.close();
}
// 高效字节流一次读写一个字节
public static void mtehod3(String srcString, String destString)
throws IOException {
// 封装数据源
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcString));
// 封装目的地
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destString));
// 复制数据
int by = 0;
while ((by = bis.read()) != -1) {
bos.write(by);
}
// 关闭资源
bos.close();
bis.close();
}
// 高效字节流一次读写一个字节数组
public static void mtehod4(String srcString, String destString)
throws IOException {
// 封装数据源
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcString));
// 封装目的地
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destString));
// 复制数据
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
// 关闭资源
bos.close();
bis.close();
}
}
运行每种方法,然后发现通过基本字节流一次读写一个字节共耗时:65937毫秒,通过基本字节流一次读写一个字节数组共耗时:127毫秒,通过高效字节流一次读写一个字节共耗时:952毫秒,通过高效字节流一次读写一个字节数组共耗时:69毫秒。说明使用缓冲区后确实提高了读写效率。
6.5 转换流
字节流操作中文数据不是特别的方便,所以就出现了转换流。转换流的作用就是把字节流转换字符流来使用。转换流其实是一个字符流。字符流 = 字节流 + 编码表
6.5.1 转换输出流
1.构造方法
OutputStreamWriter(OutputStream out):根据默认编码把字节流的数据转换为字符流
OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流
示例:
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
//创建对象
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt")); //默认GBK
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"),"GBK"); //指定GBK
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"),"UTF-8"); //指定UTF-8
//写数据
osw.write("中国");
//释放资源
osw.close();
}
}
运行结果:
2. write方法
public void write(int c):写一个字符
public void write(char[] cbuf):写一个字符数组
public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
public void write(String str):写一个字符串
public void write(String str,int off,int len):写一个字符串的一部分
示例:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
// 创建对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"osw2.txt"));
// 写数据
// public void write(int c):写一个字符
// osw.write('a');
// osw.write(97);
// 原因是:字符 = 2字节
// 文件中数据存储的基本单位是字节。
// void flush()
// public void write(char[] cbuf):写一个字符数组
// char[] chs = { 'a', 'b', 'c', 'd' };
// osw.write(chs);
// public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
// osw.write(chs,1,3);
// public void write(String str):写一个字符串
// osw.write("我爱Java");
// public void write(String str,int off,int len):写一个字符串的一部分
osw.write("我爱Java", 2, 4);
// 刷新缓冲区
osw.flush();
// 关闭资源
osw.close();
}
}
运行结果:
提问:close()和flush()的区别是什么?
close()关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了;flush()仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。
6.5.2 转换输入流
1. 构造方法
InputStreamReader(InputStream is):用默认的编码读取数据
InputStreamReader(InputStream is,String charsetName):用指定的编码读取数据
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/*
* InputStreamReader(InputStream is):用默认的编码读取数据
* InputStreamReader(InputStream is,String charsetName):用指定的编码读取数据
*/
public class InputStreamReadDemo {
public static void main(String[] args) throws IOException {
//创建对象
//InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"));
//InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"),"GBK");
InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"),"UTF-8");
//读取数据
//一次读取一个字符
int ch = 0;
while((ch = isr.read())!=-1){
System.out.print((char)ch);
}
//关闭资源
isr.close();
}
}
运行结果:
注意:使用转换输入流读取数据时,设定的编码类型必须和使用转换输出流写入数据时所用编码类型相同,否则会出现乱码现象。
2. read方法
int read():一次读取一个字符
int read(char[] chs):一次读取一个字符数组
示例:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
//创建对象
InputStreamReader isr = new InputStreamReader(new FileInputStream("StringDemo.java"));
//一次读取一个字符
int ch = 0;
while((ch = isr.read())!=-1){
System.out.print((char)ch);
}
//一次读取一个字符数组
char[] chs = new char[1024];
int len = 0;
while((len = isr.read(chs))!=-1){
System.out.println(new String(chs,0,len));
}
//释放资源
isr.close();
}
}
运行结果:
6.5.3 练习题
练习:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
/*
* 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
*
* 数据源:
* a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader
* 目的地:
* b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter
*/
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
//封装数据源
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
//封装目的地
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"));
//复制数据
// int ch = 0;
// while((ch=isr.read())!=-1){
// osw.write(ch);
// }
char[] chs = new char[1024];
int len = 0;
while((len = isr.read(chs))!=-1){
osw.write(chs,0,len);
osw.flush();
}
//关闭资源
osw.close();
isr.close();
}
}
运行前(a.txt文件):
运行后(b.txt文件):
6.6 字符流
6.6.1 字符流的基本使用
由于我们常见的操作都是使用本地默认编码,所以,不用指定编码。而转换流的名称有点长,所以,Java就提供了其子类供我们使用。
OutputStreamWriter = FileOutputStream + 编码表(GBK)
FileWriter = FileOutputStream + 编码表(GBK)
InputStreamReader = FileInputStream + 编码表(GBK)
FileReader = FileInputStream + 编码表(GBK)
由此看来字符流的使用和转换流的使用几乎一样。
示例:
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
*
* 数据源:
* a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader
* 目的地:
* b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter -- FileWriter
*/
public class CopyFileDemo2 {
public static void main(String[] args) throws IOException{
//封装数据源
FileReader fr = new FileReader("a.txt");
//封装目的地
FileWriter fw = new FileWriter("b.txt");
//一次一个字符
// int ch = 0;
// while((ch= fr.read())!=-1){
// fw.write(ch);
// }
//一次一个字符数组
char[] chs = new char[1024];
int len = 0;
while((len = fr.read(chs))!=-1){
fw.write(chs,0,len);
}
//关闭资源
fw.close();
fr.close();
}
}
运行前(a.txt):
运行后(b.txt):
6.6.2 字符缓冲流
1. BufferedReader
示例:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedFileWriterDemo {
public static void main(String[] args) throws IOException {
// BufferedWriter(Writer out)
// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("bw.txt")));
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
bw.write("hello");
bw.write("world");
bw.write("java");
bw.flush();
bw.close();
}
}
运行结果:
2. BufferedReader
示例:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedFileReaderDemo {
public static void main(String[] args) throws IOException {
//创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
//方式1:
// int ch = 0;
// while((ch = br.read())!=-1){
// System.out.print((char)ch);
// }
//
//方式2:
char[] chs = new char[1024];
int len =0;
while((len = br.read(chs))!=-1){
System.out.print(new String(chs,0,len));
}
//释放资源
br.close();
}
}
运行结果:
3. 字符缓冲流的特殊方法
BufferedWriter:
public void newLine():根据系统来决定换行符
BufferedReader:
public String readLine():一次读取一行数据,包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
示例:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedDemo {
public static void main(String[] args) throws IOException {
// write();
read();
}
public static void read() throws IOException {
// 创建字符创缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("bw2.txt"));
// public String readLine():一次读取一行数据
// String line = br.readLine();
// System.out.print(line);
// line = br.readLine();
// System.out.print(line);
String line = null;
while((line = br.readLine())!=null){
System.out.println(line);
}
br.close();
}
public static void write() throws IOException {
// 创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("bw2.txt"));
for (int x = 0; x < 10; x++) {
bw.write("hello" + x);
// bw.write("\r\n");
bw.newLine();
bw.flush();
}
bw.close();
}
}
运行结果:
6.7 IO练习题
练习1:使用字符流的5种方式来复制文本文件
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 复制文本文件
*
* 分析:
* 复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。
* 通过该原理,我们知道我们应该采用字符流更方便一些。
* 而字符流有5种方式,所以做这个题目我们有5种方式。推荐掌握第5种。
* 数据源:
* c:\\a.txt -- FileReader -- BufferdReader
* 目的地:
* d:\\b.txt -- FileWriter -- BufferedWriter
*/
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
String srcString = "c:\\a.txt";
String destString = "d:\\b.txt";
// method1(srcString, destString);
// method2(srcString,destString);
// method3(srcString, destString);
// method4(srcString,destString);
method5(srcString, destString);
}
// 字符缓冲流一次读取一行
public static void method5(String srcString, String destString)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(srcString));
BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
// 字符缓冲流一次读取一个字符数组
public static void method4(String srcString, String destString)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(srcString));
BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
char[] chs = new char[1024];
int len = 0;
while ((len = br.read(chs)) != -1) {
bw.write(chs, 0, len);
}
bw.close();
br.close();
}
// 字符缓冲流一次读取一个字符
public static void method3(String srcString, String destString)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(srcString));
BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
int ch = 0;
while ((ch = br.read()) != -1) {
bw.write(ch);
}
bw.close();
br.close();
}
// 基本字符流一次读取一个字符数组
public static void method2(String srcString, String destString)
throws IOException {
FileReader fr = new FileReader(srcString);
FileWriter fw = new FileWriter(destString);
char[] chs = new char[1024];
int len = 0;
while ((len = fr.read(chs)) != -1) {
fw.write(chs, 0, len);
}
fw.close();
fr.close();
}
// 基本字符流一次读取一个字符
public static void method1(String srcString, String destString)
throws IOException {
FileReader fr = new FileReader(srcString);
FileWriter fw = new FileWriter(destString);
int ch = 0;
while ((ch = fr.read()) != -1) {
fw.write(ch);
}
fw.close();
fr.close();
}
}
练习2:使用字节流的4种方式来复制图片
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 复制图片
*
* 分析:
* 复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。
* 通过该原理,我们知道我们应该采用字节流。
* 而字节流有4种方式,所以做这个题目我们有4种方式。推荐掌握第4种。
*
* 数据源:
* c:\\a.jpg -- FileInputStream -- BufferedInputStream
* 目的地:
* d:\\b.jpg -- FileOutputStream -- BufferedOutputStream
*/
public class CopyImageDemo {
public static void main(String[] args) throws IOException {
String srcString = "c:\\a.jpg";
String destString = "d:\\b.jpg";
// method1(srcString,destString);
method2(srcString, destString);
// method3(srcString,destString);
// method4(srcString,destString);
}
// 字节缓冲流一次读取一个字节
public static void method4(String srcString, String destString)
throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcString));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destString));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys,0,len);
}
bos.close();
bis.close();
}
// 字节缓冲流一次读取一个字节
public static void method3(String srcString, String destString)
throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcString));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destString));
int by = 0;
while ((by = bis.read()) != -1) {
bos.write(by);
}
bos.close();
bis.close();
}
// 基本字节流一次读取一个字节数组
public static void method2(String srcString, String destString)
throws IOException {
FileInputStream fis = new FileInputStream(srcString);
FileOutputStream fos = new FileOutputStream(destString);
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
fos.close();
fis.close();
}
// 基本字节流一次读取一个字节
public static void method1(String srcString, String destString)
throws IOException {
FileInputStream fis = new FileInputStream(srcString);
FileOutputStream fos = new FileOutputStream(destString);
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}
fos.close();
fis.close();
}
}
练习3:把ArrayList集合中的字符串数据存储到文本文件
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
/*
* 需求:把ArrayList集合中的字符串数据存储到文本文件
*
* 分析:
* 通过题目的意思我们可以知道如下的一些内容,
* ArrayList集合里存储的是字符串。
* 遍历ArrayList集合,把数据获取到。
* 然后存储到文本文件中。
* 文本文件说明使用字符流。
*
* 数据源:
* ArrayList<String> -- 遍历得到每一个字符串数据
* 目的地:
* a.txt -- FileWriter -- BufferedWriter
*/
public class ArrayListToFileDemo {
public static void main(String[] args) throws IOException {
//封装数据源(创建集合对象)
ArrayList<String> array = new ArrayList<String>();
array.add("hello");
array.add("world");
array.add("java");
//封装目的地
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
//遍历集合
for(String s:array){
//写入数据
bw.write(s);
bw.newLine();
bw.flush();
}
//关闭资源
bw.close();
}
}
运行结果:
练习4:把文本中的字符串存储到ArrayList集合中
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class FileToArrayListDemo {
public static void main(String[] args) throws IOException {
//封装数据源
BufferedReader br = new BufferedReader(new FileReader("b.txt"));
//封装目的地
ArrayList<String> array = new ArrayList<String>();
// 读取数据存储到集合中
String line = null;
while((line = br.readLine())!=null){
array.add(line);
}
//关闭资源
br.close();
// 遍历集合
for(String s :array){
System.out.println(s);
}
}
}
运行结果:
练习5:我有一个文本文件中存储了几个名称,请大家写一个程序实现随机获取一个人的名字。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
/*
* 需求:我有一个文本文件中存储了几个名称,请大家写一个程序实现随机获取一个人的名字。
*
* 分析:
* A:把文本文件中的数据存储到集合中
* B:随机产生一个索引
* C:根据该索引获取一个值
*/
public class GetName {
public static void main(String[] args) throws IOException {
// 把文本中的数据存储到集合中
BufferedReader br = new BufferedReader(new FileReader("b.txt"));
ArrayList<String> array = new ArrayList<String>();
String line = null;
while ((line = br.readLine()) != null) {
array.add(line);
}
// 随机产生一个索引
Random r = new Random();
int index = r.nextInt(array.size());
// 根据该索引获取一个值
String name = array.get(index);
System.out.println("该幸运者是:"+name);
}
}
运行结果:
练习6:复制单极文件夹
/*
* 需求:复制单极文件夹
*
* 数据源:g:\\demo
* 目的地:g:\\test
*
* 分析:
* A:封装目录
* B:获取该目录下的所有文本的File数组
* C:遍历该File数组,得到每一个File对象
* D:把该File进行复制
*/
public class CopyFloderDemo {
public static void main(String[] args) throws IOException {
// 封装目录
File srcFloder = new File("g:\\demo");
// 封装目的地
File destFloder = new File("g:\\test");
// 由于写数据时,如果文件不存在,系统可以自动创建,但是文件夹不行,必须手动创建
if (!destFloder.exists()) {
destFloder.mkdir();
}
// 获取该目录下的File数组
File[] fileArray = srcFloder.listFiles();
for (File file : fileArray) {
// 数据源:g:\\demo\\e.mp3
// 目的地:g:\\test\\e.mp3
String name = file.getName();
File newFile = new File(destFloder, name);
copyFile(file, newFile);
}
}
public static void copyFile(File file, File newFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
file));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(newFile));
byte[] bys = new byte[1024];
int len = 0;
while((len = bis.read(bys))!=-1){
bos.write(bys,0,len);
}
bos.close();
bis.close();
}
}
练习7:复制指定目录下的指定格式文件,并修改后缀名。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
/*
* 需求:复制指定目录下的指定格式文件,并修改后缀名。
* 指定的文件是:.java文件。
* 指定的后缀名是:.jad
* 指定的目的地目录是:jad
*
* 数据源:g:\\java\\A.java
* 目的地:g:\\jad\\A.jad
*
* 分析:
* A:封装目录
* B:获取该目录下的java文件的File数组
* C:遍历该File数组,得到每一个File对象
* D:把该File进行复制
* E:在目的地目录下改名
*/
public class CopyFolderDemo {
public static void main(String[] args) throws IOException {
// 封装目录
File srcFolder = new File("g:\\java");
File destFolder = new File("g:\\jad");
if (!destFolder.exists()) {
destFolder.mkdir();
}
// 获取该目录下的java文件的File数组
File[] fileArray = srcFolder.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isFile()
&& new File(dir, name).getName().endsWith(".java");
}
});
// 遍历该File数组,得到每一个File对象
for (File file : fileArray) {
File newFile = new File(destFolder, file.getName());
copyFile(file, newFile);
}
// 在目的地目录下改名
renameToJad(destFolder);
}
public static void renameToJad(File Floder) {
File[] fileArray = Floder.listFiles();
for (File file : fileArray) {
String name = file.getName();
// int index = name.lastIndexOf(".");
// String tempName = name.substring(0, index);
// String newName = tempName.concat(".jad");
String newName = name.replace(".java", ".jad");
System.out.println(newName);
File newFile = new File(Floder, newName);
file.renameTo(newFile);
}
}
private static void copyFile(File file, File newFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
file));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(newFile));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
}
}
练习8:复制多极文件夹
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 需求:复制多极文件夹
*
* 数据源:F:\\code\\demos
* 目的地:G:\\
*
* 分析:
* A:封装数据源File
* B:封装目的地File
* C:判断该File是文件夹还是文件
* a:是文件夹
* 就在目的地目录下创建该文件夹
* 获取该File对象下的所有文件或者文件夹File对象
* 遍历得到每一个File对象
* 回到C
* b:是文件
* 就在目的地目录下创建该文件
* 复制(字节流)
*/
public class CopyFoldersDemo {
public static void main(String[] args) throws IOException {
// 封装数据源
File srcFolder = new File("F:\\code\\demos");
// 封装目的地
File destFolder = new File("G:\\");
copyFolder(srcFolder, destFolder);
}
public static void copyFolder(File srcFile, File destFile)
throws IOException {
// 判断该File是否是文件夹
if (srcFile.isDirectory()) {
// 文件夹
// 在目的地目录创建该文件夹
File newFolder = new File(destFile,srcFile.getName());
newFolder.mkdir();
// 获取该File对象下的所有文件或者文件夹File对象
File[] fileArray = srcFile.listFiles();
for (File file : fileArray) {
copyFolder(file, newFolder);
}
} else {
// 文件
File newFile = new File(destFile,srcFile.getName());
copyFile(srcFile, newFile);
}
}
public static void copyFile(File srcFile, File destFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcFile));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destFile));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
}
}
练习9:已知s.txt文件中有这样的一个字符串:“hcexfgijkamdnoqrzstuvwybpl”,请编写程序读取数据内容,把数据排序后写入ss.txt中。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
/*
* 已知s.txt文件中有这样的一个字符串:“hcexfgijkamdnoqrzstuvwybpl”
* 请编写程序读取数据内容,把数据排序后写入ss.txt中。
*
* 分析:
* A:把s.txt这个文件给做出来
* B:读取该文件的内容,存储到一个字符串中
* C:把字符串转换为字符数组
* D:对字符数组进行排序
* E:把排序后的字符数组转换为字符串
* F:把字符串再次写入ss.txt中
*/
public class StringDemo {
public static void main(String[] args) throws IOException {
// 读取该文件的内容,存储到一个字符串中
BufferedReader br = new BufferedReader(new FileReader("s.txt"));
String line = br.readLine();
br.close();
// 把字符串转换为字符数组
char[] chs = line.toCharArray();
// 对字符数组进行排序
Arrays.sort(chs);
// 把排序后的字符数组转换为字符串
line = new String(chs);
// 把字符串再次写入ss.txt中
BufferedWriter bw = new BufferedWriter(new FileWriter("ss.txt"));
bw.write(line);
bw.newLine();
bw.flush();
bw.close();
}
}
运行结果:
练习10:用Reader模拟BufferedReader的readLine()功能。
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class MyBufferedReader {
private Reader r;
public MyBufferedReader(Reader r) {
this.r = r;
}
/*
* 思考:写一个方法,返回值是一个字符串。
*/
public String readLine() throws IOException {
/*
* 我要返回一个字符串,我该怎么办呢? 我们必须去看看r对象能够读取什么东西呢? 两个读取方法,一次读取一个字符或者一次读取一个字符数组
* 那么,我们要返回一个字符串,用哪个方法比较好呢? 我们很容易想到字符数组比较好,但是问题来了,就是这个数组的长度是多长呢?
* 根本就没有办法定义数组的长度,你定义多长都不合适。 所以,只能选择一次读取一个字符。
* 但是呢,这种方式的时候,我们再读取下一个字符的时候,上一个字符就丢失了 所以,我们又应该定义一个临时存储空间把读取过的字符给存储起来。
* 这个用谁比较和是呢?数组,集合,字符串缓冲区三个可供选择。
* 经过简单的分析,最终选择使用字符串缓冲区对象。并且使用的是StringBuilder
*/
StringBuilder sb = new StringBuilder();
// 做这个读取最麻烦的是判断结束,但是在结束之前应该是一直读取,直到-1
int ch = 0;
while ((ch = r.read()) != -1) {
if (ch == 'r') {
continue;
}
if (ch == '\n') {
return sb.toString();
}
else {
sb.append((char) ch);
}
}
// 为了防止数据丢失,判断sb的长度不能大于0
if (sb.length() > 0) {
return sb.toString();
}
return null;
}
/*
* 先写一个关闭方法
*/
public void close() throws IOException {
this.r.close();
}
}
public class MyBufferedReaderDemo {
public static void main(String[] args) throws IOException {
MyBufferedReader mbr = new MyBufferedReader(new FileReader("my.txt"));
String line = null;
while((line = mbr.readLine())!=null){
System.out.print(line);
}
mbr.close();
// System.out.println('\r'+0);
// System.out.println('\n'+0);
}
}
运行结果:
练习11:自定义类模拟LineNumberReader的获取行号功能案例
练习12:登录注册模拟案例IO版实现