Java-IO-2
复制文本文件
/*
* 思路:
* 1,需要读取源,
* 2,将读到的源数据写入到目的地。
* 3,既然是操作文本数据,使用字符流。
*/
public class CopyTextTest {
public static void main(String[] args) throws IOException {
//1,读取一个已有的文本文件,使用字符读取流和文件相关联。
FileReader fr = new FileReader("IO流_2.txt");
//2,创建一个目的,用于存储读到数据。
FileWriter fw = new FileWriter("copytext_1.txt");
//3,频繁的读写操作。
int ch = 0;
while((ch=fr.read())!=-1){
fw.write(ch);
}
//4,关闭流资源。
fw.close();
fr.close();
}
}
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyTextTest_2 {
private static final int BUFFER_SIZE = 1024;
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("IO流_2.txt");
fw = new FileWriter("copytest_2.txt");
//创建一个临时容器,用于缓存读取到的字符。
char[] buf = new char[BUFFER_SIZE];//这就是缓冲区。
//定义一个变量记录读取到的字符数,(其实就是往数组里装的字符个数 )
int len = 0;
while((len=fr.read(buf))!=-1){
fw.write(buf, 0, len);
}
} catch (Exception e) {
// System.out.println("读写失败");
throw new RuntimeException("读写失败");
}finally{
if(fw!=null)
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
if(fr!=null)
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
.
使用缓冲区复制一个文本文件:
字符流缓冲区:
BufferedWriter
:newLine();
BufferedReader:
: readLine();
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("buf.txt");
BufferedReader bufr = new BufferedReader(fr);
String line = null;
while((line=bufr.readLine())!=null){
System.out.println(line);
}
/*
String line1 = bufr.readLine();
System.out.println(line1);
String line2 = bufr.readLine();
System.out.println(line2);
String line3 = bufr.readLine();
System.out.println(line3);
String line4 = bufr.readLine();
System.out.println(line4);
String line5 = bufr.readLine();
System.out.println(line5);
*/
bufr.close();
}
/**
* @throws FileNotFoundException
* @throws IOException
*/
public static void demo() throws FileNotFoundException, IOException {
FileReader fr = new FileReader("buf.txt");
char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
fr.close();
}
}
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo {
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("buf.txt");
//为了提高写入的效率。使用了字符流的缓冲区。
//创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联
BufferedWriter bufw = new BufferedWriter(fw);
//使用缓冲区的写入方法将数据先写入到缓冲区中。
// bufw.write("abcdefq"+LINE_SEPARATOR+"hahahha");
// bufw.write("xixiixii");
// bufw.newLine();
// bufw.write("heheheheh");
for(int x=1; x<=4; x++){
bufw.write("abcdef"+x);
bufw.newLine();
bufw.flush();
}
//使用缓冲区的刷新方法将数据刷目的地中。
// bufw.flush();
//关闭缓冲区。其实关闭的就是被缓冲的流对象。
bufw.close();
// fw.write("hehe");
// fw.close();
}
}
用BufferedReader、BufferedWriter复制文本:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyTextByBufTest {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("buf.txt");
BufferedReader bufr = new BufferedReader(fr);
FileWriter fw = new FileWriter("buf_copy.txt");
BufferedWriter bufw = new BufferedWriter(fw);
String line = null;
while((line=bufr.readLine())!=null){
bufw.write(line);
bufw.newLine();
bufw.flush();
}
bufw.close();
bufr.close();
}
}
自定义缓冲区
import java.io.IOException;
import java.io.Reader;
/**
* 自定义的读取缓冲区。其实就是模拟一个BufferedReader.
*
* 分析:
* 缓冲区中无非就是封装了一个数组,
* 并对外提供了更多的方法对数组进行访问。
* 其实这些方法最终操作的都是数组的角标。
*
* 缓冲的原理:
* 其实就是从源中获取一批数据装进缓冲区中。
* 在从缓冲区中不断的取出一个一个数据。
*
* 在此次取完后,在从源中继续取一批数据进缓冲区。
* 当源中的数据取光时,用-1作为结束标记。
* @author Administrator
*/
public class MyBufferedReader extends Reader {
private Reader r;
//定义一个数组作为缓冲区。
private char[] buf = new char[1024];
//定义一个指针用于操作这个数组中的元素。当操作到最后一个元素后,指针应该归零。
private int pos = 0;
//定义一个计数器用于记录缓冲区中的数据个数。 当该数据减到0,就从源中继续获取数据到缓冲区中。
private int count = 0;
MyBufferedReader(Reader r){
this.r = r;
}
/**
* 该方法从缓冲区中一次取一个字符。
* @return
* @throws IOException
*/
public int myRead() throws IOException{
if(count==0){
count = r.read(buf);
pos = 0;
}
if(count<0)
return -1;
char ch = buf[pos++];
count--;
return ch;
}
public String myReadLine() throws IOException{
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch = myRead())!=-1){
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
//将从缓冲区中读到的字符,存储到缓存行数据的缓冲区中。
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
public void myClose() throws IOException {
r.close();
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return 0;
}
@Override
public void close() throws IOException {
}
}
装饰设计模式:
对一组对象的功能进行增强时,就可以使用该模式进行问题的解决。
装饰和继承都能实现一样的特点:进行功能的扩展增强。
public class PersonDemo {
/**
* @param args
*/
public static void main(String[] args) {
Person p = new Person();
// p.chifan();
NewPerson p1 = new NewPerson(p);
p1.chifan();
NewPerson2 p2 = new NewPerson2();
p2.chifan();
}
}
class Person{
void chifan(){
System.out.println("吃饭");
}
}
//这个类的出现是为了增强Person而出现的。
class NewPerson{
private Person p ;
NewPerson(Person p){
this.p = p;
}
public void chifan(){
System.out.println("开胃酒");
p.chifan();
System.out.println("甜点");
}
}
class NewPerson2 extends Person{
public void chifan(){
System.out.println("开胃酒");
super.chifan();
System.out.println("甜点");
}
}
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体。
想要对操作的动作进行效率的提高。
按照面向对象,可以通过继承对具体的进行功能的扩展。
效率提高需要加入缓冲技术。
Writer
|--TextWriter:用于操作文本
|--BufferTextWriter:加入了缓冲技术的操作文本的对象。
|--MediaWriter:用于操作媒体。
|--BufferMediaWriter:
如果这个体系进行功能扩展,有多个流对象。
那么这个流要提高效率,是不是也要产生子类呢?
是。这时就会发现只为提高功能,进行的继承,导致继承体系越来越臃肿。不够灵活。
重新思考这个问题?
既然加入的都是同一种技术--缓冲。
前一种是让缓冲和具体的对象相结合。
可不可以将缓冲进行单独的封装,哪个对象需要缓冲就将哪个对象和缓冲关联。
class Buffer{
Buffer(TextWriter w){ }
Buffer(MediaWirter w){ }
}
class BufferWriter extends Writer{
BufferWriter(Writer w){
}
}
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体。
|--BufferWriter:用于提高效率。
装饰比继承灵活。
特点:装饰类和被装饰类都必须所属同一个接口或者父类。
LineNumberReader
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
public class LineNumberReaderDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("IO流_2.txt");
LineNumberReader lnr = new LineNumberReader(fr);
String line = null;
lnr.setLineNumber(0);
while((line=lnr.readLine())!=null){
System.out.println(lnr.getLineNumber()+":"+line);
}
lnr.close();
}
}
字节流:
InputStream
OutputStream
字节流:
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
字符流:
Writer Reader
FileReader
FileWriter
BufferedReader
BufferedWriter
.
.
.
转换流:
InputStreamReader :字节到字符的桥梁。解码。
OutputStreamWriter:字符到字节的桥梁。编码。
流的操作规律:
之所以要弄清楚这个规律,是因为流对象太多,开发时不知道用哪个对象合适。
想要知道开发时用到哪些对象。只要通过四个明确即可。
1,明确源和目的(汇)
源:InputStream Reader
目的:OutputStream Writer
2,明确数据是否是纯文本数据。
源:是纯文本:Reader
否:InputStream
目的:是纯文本 Writer
否:OutputStream
到这里,就可以明确需求中具体要使用哪个体系。
3,明确具体的设备。
源设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
目的设备:
硬盘:File
控制台:System.out
内存:数组
网络:Socket流
4,是否需要其他额外功能。
1,是否需要高效(缓冲区);
是,就加上buffer.
2,转换。
读取一个键盘录入的数据,并打印在控制台上。
键盘本身就是一个标准的输入设备。
对于java而言,对于这种输入设备都有对应的对象。
public class ReadKey {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// readKey();
// System.out.println((int)'\r');
// System.out.println((int)'\n');
readKey2();
}
public static void readKey2() throws IOException {
/*
* 获取用户键盘录入的数据,
* 并将数据变成大写显示在控制台上,
* 如果用户输入的是over,结束键盘录入。
*
* 思路:
* 1,因为键盘录入只读取一个字节,要判断是否是over,需要将读取到的字节拼成字符串。
* 2,那就需要一个容器。StringBuilder.
* 3,在用户回车之前将录入的数据变成字符串判断即可。
*/
//1,创建容器。
StringBuilder sb = new StringBuilder();
//2,获取键盘读取流。
InputStream in = System.in;
//3,定义变量记录读取到的字节,并循环获取。
int ch = 0;
while((ch=in.read())!=-1){
// 在存储之前需要判断是否是换行标记 ,因为换行标记不存储。
if(ch=='\r')
continue;
if(ch=='\n'){
String temp = sb.toString();
if("over".equals(temp))
break;
System.out.println(temp.toUpperCase());
sb.delete(0, sb.length());
}
else
//将读取到的字节存储到StringBuilder中。
sb.append((char)ch);
}
}
public static void readKey() throws IOException {
InputStream in = System.in;
int ch = in.read();//阻塞式方法。
System.out.println(ch);
int ch1 = in.read();//阻塞式方法。
System.out.println(ch1);
int ch2 = in.read();//阻塞式方法。
System.out.println(ch2);
// in.close();
// InputStream in2 = System.in;
// int ch3 = in2.read();
}
}
打印结果:
ssss
SSSS
sqdqdwq
SQDQDWQ
vcvxcv
VCVXCV
over
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
public class TransStreamDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//字节流。
InputStream in = System.in;
//将字节转成字符的桥梁。装换流。
InputStreamReader isr = new InputStreamReader(in);
//字符流。
BufferedReader bufr = new BufferedReader(isr);
OutputStream out = System.out;
OutputStreamWriter osw = new OutputStreamWriter(out);
BufferedWriter bufw = new BufferedWriter(osw);
String line = null;
while((line=bufr.readLine())!=null){
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
}
}
/*
* 1,需求:将键盘录入的数据写入到一个文件中。
*
* 2,需求:将一个文本文件内容显示在控制台上。
*
* 3,需求:将一个文件文件中的内容复制到的另一个文件中。
*/
public static void main(String[] args) throws IOException {
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("b.txt")));
String line = null;
while((line=bufr.readLine())!=null){
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
public class TransStreamDemo3 {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
readText_2();
}
public static void readText_2() throws IOException, FileNotFoundException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk_1.txt"),"gbk");
char[] buf = new char[10];
int len = isr.read(buf);
String str = new String(buf,0,len);
System.out.println(str);
isr.close();
}
public static void readText_1() throws IOException {
FileReader fr = new FileReader("gbk_1.txt");
char[] buf = new char[10];
int len = fr.read(buf);
String str = new String(buf,0,len);
System.out.println(str);
fr.close();
}
public static void writeText_3() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("u8_1.txt"),"UTF-8");
osw.write("你好");
osw.close();
}
public static void writeText_2() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk_3.txt"),"GBK");
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk_3.txt"),"GBK");
// FileWriter fw = new FileWriter("gbk_1.txt");
/*
* 这两句代码的功能是等同的。
* FileWriter:其实就是转换流指定了本机默认码表的体现。而且这个转换流的子类对象,可以方便操作文本文件。
* 简单说:操作文件的字节流+本机默认的编码表。
* 这是按照默认码表来操作文件的便捷类。
* 如果操作文本文件需要明确具体的编码。FileWriter就不行了。必须用转换流。
*/
osw.write("你好");
osw.close();
}
public static void writeText_1() throws IOException {
FileWriter fw = new FileWriter("gbk_1.txt");
fw.write("你好");
fw.close();
}
}
总结:
需求1:复制一个文本文件。
1,明确源和目的。
源:InputStream Reader
目的:OutputStream Writer
2,是否是纯文本?
是!
源:Reader
目的:Writer
3,明确具体设备。
源:
硬盘:File
目的:
硬盘:File
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
4,需要额外功能吗?
需要,需要高效。
BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));
================================================
需求2:读取键盘录入信息,并写入到一个文件中。
1,明确源和目的。
源:InputStream Reader
目的:OutputStream Writer
2,是否是纯文本呢?
是,
源:Reader
目的:Writer
3,明确设备
源:
键盘。System.in
目的:
硬盘。File
InputStream in = System.in;
FileWriter fw = new FileWriter("b.txt");
这样做可以完成,但是麻烦。将读取的字节数据转成字符串。再由字符流操作。
4,需要额外功能吗?
需要。转换。 将字节流转成字符流。因为名确的源是Reader,这样操作文本数据做便捷。
所以要将已有的字节流转成字符流。使用字节-->字符 。InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
FileWriter fw = new FileWriter("b.txt");
还需要功能吗?
需要:想高效。
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));
===================================================
需求3:将一个文本文件数据显示在控制台上。
1,明确源和目的。
源:InputStream Reader
目的:OutputStream Writer
2,是否是纯文本呢?
是,
源:Reader
目的:Writer
3,明确具体设备
源:
硬盘:File
目的:
控制台:System.out
FileReader fr = new FileReader("a.txt");
OutputStream out = System.out;//PrintStream
4,需要额外功能吗?
需要,转换。
FileReader fr= new FileReader("a.txt");
OutputStreamWriter osw = new OutputStreamWriter(System.out);
需要,高效。
BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
================================================================
需求4:读取键盘录入数据,显示在控制台上。
1,明确源和目的。
源:InputStream Reader
目的:OutputStream Writer
2,是否是纯文本呢?
是,
源:Reader
目的:Writer
3,明确设备。
源:
键盘:System.in
目的:
控制台:System.out
InputStream in = System.in;
OutputStream out = System.out;
4,明确额外功能?
需要转换,因为都是字节流,但是操作的却是文本数据。
所以使用字符流操作起来更为便捷。
InputStreamReader isr = new InputStreamReader(System.in);
OutputStreamWriter osw = new OutputStreamWriter(System.out);
为了将其高效。
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
============================================================
5,将一个中文字符串数据按照指定的编码表写入到一个文本文件中.
1,目的。OutputStream,Writer
2,是纯文本,Writer。
3,设备:硬盘File
FileWriter fw = new FileWriter("a.txt");
fw.write("你好");
注意:既然需求中已经明确了指定编码表的动作。
那就不可以使用FileWriter,因为FileWriter内部是使用默认的本地码表。
只能使用其父类。OutputStreamWriter.
OutputStreamWriter接收一个字节输出流对象,既然是操作文件,那么该对象应该是FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"),charsetName);
需要高效吗?
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt"),charsetName));
什么时候使用转换流呢?
1,源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁。
提高对文本操作的便捷。
2,一旦操作文本涉及到具体的指定编码表时,必须使用转换流 。
File类
import java.io.File;
import cn.itcast.io.p2.filter.FilterByHidden;
import cn.itcast.io.p2.filter.SuffixFilter;
public class FileListDemo {
/**
* @param args
*/
public static void main(String[] args) {
listDemo();
}
public static void listDemo_3() {
// 获取当前目录下的文件以及文件夹的名称
File dir = new File("E:\\");
File[] files = dir.listFiles(new FilterByHidden());
for(File file : files){
System.out.println(file);
}
}
public static void listDemo_2() {
// 获取当前目录下的txt格式的文件
File dir = new File("E:\\");
String[] names = dir.list(new SuffixFilter(".txt"));
for(String name : names){
System.out.println(name);
}
}
public static void listDemo() {
File file = new File("E:\\");
/*
* 获取当前目录下的文件以及文件夹的名称,包含隐藏文件。
* 调用list方法的File对象中封装的必须是目录。
* 否则会发生NullPointerException
* 如果访问的系统级目录也会发生空指针异常。
*
* 如果目录存在但是没有内容,会返回一个数组,但是长度为0.
*/
String[] names = file.list();
System.out.println(names.length);
for(String name : names){
System.out.println(name);
}
}
}
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
public class FileMethodDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
/*
* File对象的常见方法。
* 1,获取。
* 1.1 获取文件名称。
* 1.2 获取文件路径。
* 1.3 获取文件大小。
* 1.4 获取文件修改时间。
* 2,创建与删除。
* 3,判断。
* 4, 重命名
*/
// getDemo();
// createAndDeleteDemo();
// isDemo();
// renameToDemo();
// listRootsDemo();
}
public static void listRootsDemo() {
File file = new File("d:\\");
System.out.println("getFreeSpace:"+file.getFreeSpace());
System.out.println("getTotalSpace:"+file.getTotalSpace());
System.out.println("getUsableSpace:"+file.getUsableSpace());
// File[] files = File.listRoots();
// for(File file : files){
// System.out.println(file);
// }
}
public static void renameToDemo() {
File f1 = new File("c:\\9.mp3");
File f2 = new File("d:\\aa.mp3");
boolean b = f1.renameTo(f2);
System.out.println("b="+b);
}
public static void isDemo() throws IOException{
File f = new File("aaa");
// f.mkdir();
f.createNewFile();
// boolean b = f.exists();
// System.out.println("b="+b);
// 最好先判断是否存在。
System.out.println(f.isFile());
System.out.println(f.isDirectory());
}
public static void createAndDeleteDemo() throws IOException {
File dir = new File("abc\\q\\e\\c\\z\\r\\w\\y\\f\\e\\g\\s");
// boolean b = dir.mkdir();//make directory
// System.out.println("b="+b);
// dir.mkdirs();//创建多级目录
System.out.println(dir.delete());
// System.out.println(dir.delete());
// 文件的创建和删除。
// File file = new File("file.txt");
/*
* 和输出流不一样,如果文件不存在,则创建,如果文件存在,则不创建。
*/
// boolean b = file.createNewFile();
// System.out.println("b="+b);
// boolean b = file.delete();
// System.out.println("b="+b);
}
public static void getDemo(){
// File file = new File("E:\\java0331\\day22e\\a.txt");
File file = new File("a.txt");
String name = file.getName();
String absPath = file.getAbsolutePath();//绝对路径。
String path = file.getPath();
long len = file.length();
long time = file.lastModified();
Date date = new Date(time);
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
String str_time = dateFormat.format(date);
System.out.println("parent:"+file.getParent());
System.out.println("name:"+name);
System.out.println("absPath:"+absPath);
System.out.println("path:"+path);
System.out.println("len:"+len);
System.out.println("time:"+time);
System.out.println("str_time:"+str_time);
}
}
txt格式文件后缀
import java.io.File;
import java.io.FilenameFilter;
public class FilterByJava implements FilenameFilter {
@Override
public boolean accept(File dir, String name) {
// System.out.println(dir+"---"+name);
return name.endsWith(".txt");
}
}
任何格式文件后缀
import java.io.File;
import java.io.FilenameFilter;
public class SuffixFilter implements FilenameFilter {
private String suffix ;
public SuffixFilter(String suffix) {
super();
this.suffix = suffix;
}
@Override
public boolean accept(File dir, String name) {
return name.endsWith(suffix);
}
}