IO总结

网友投稿 518 2022-05-29

一、概念:IO流用来处理设备之间的数据传输

Java对数据的操作是通过流的方式

Java用于操作流的对象都在IO包中

流按操作数据分为两种:字节流与字符流。

流按流向分为:输入流,输出流。

二、IO流常用基类

字节流的抽象基类:

• InputStream , OutputStream。

字符流的抽象基类:

• Reader , Writer。

注:由这四个类派生出来的子类名称都是

以其父类名作为子类名的后缀。

• 如: InputStream的子类FileInputStream。

• 如: Reader的子类FileReader

三、字符流——创建文件

 创建流对象,建立数据存放文件

• FileWriter fw = new FileWriter(“Test.txt”);

 调用流对象的写入方法,将数据写入流

• fw.write(“text”);

 关闭流资源,并将流中的数据清空到文件中。

• fw.close();

1、写文件

例:package aaa;

import java.io.FileWriter;

import java.io.IOException;

public class FileWriterDemo {

public static void main(String[] args) throws IOException {

//创建一个可以往文件中写入字符数据的字符输出流对象。

/*

* 既然是往一个文件中写入文字数据,那么在创建对象时,就必须明确该文件(用于存储数据的目的地)。

* 如果文件不存在,则会自动创建。

* 如果文件存在,则会被覆盖。

* 如果构造函数中加入true,可以实现对文件进行续写!

*/

FileWriter fWriter = new FileWriter("D:demo.txt",true);

/*

* 调用Writer对象中的write(string)方法,写入数据。

* 其实数据写入到临时存储缓冲区中。

*/

fWriter.write("adfsadfsafa");

fWriter.flush();//进行刷新,将数据直接写到目的地中。

fWriter.write("dtrdtrd");//关闭流,关闭资源。在关闭前会先调用flush刷新缓冲中的数据到目的地。

fWriter.close();

}

}

完整的写法:

private static final String LINE_SEPARATOR = System.getProperty("line.separator");//换行

public static void main(String[] args) {

FileWriter fw = null;

try {

fw = new FileWriter("k:\demo.txt");

fw.write("abcde" + LINE_SEPARATOR + "hahaha");

} catch (IOException e) {

System.out.println(e.toString());

} finally {

if (fw != null)

try {

fw.close();

} catch (IOException e) {

// code....

throw new RuntimeException("关闭失败");

}

}

}

四、字符流——读取文件

建立一个流对象,将已存在的一个文件加载进

流。

• FileReader fr = new FileReader(“Test.txt”);

创建一个临时存放数据的数组。

• char[] ch = new char[1024];

调用流对象的读取方法将流中的数据读入到数组

中。

• fr.read(ch);

2、读文件:需求:读取一个文本文件。将读取到的字符打印到控制台.

//第一种写法

package cn.itcast.p3.io.filereader;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

public class FileReaderDemo {

public static void main(String[] args) throws IOException {

//1,创建读取字符数据的流对象。

/*

* 在创建读取流对象时,必须要明确被读取的文件。一定要确定该文件是存在的。

* 用一个读取流关联一个已存在文件。

*/

FileReader fr = new FileReader("demo.txt");

int ch = 0;

while((ch=fr.read())!=-1){

System.out.println((char)ch);

这两种写法的区别:第一种一次只能读取一个字符,第二种写法一次能读取多个字符,减少循环。所以第二种写法更有优势。

}

fr.close();

}

}

//第二种写法:

package cn.itcast.p3.io.filereader;

import java.io.FileReader;

import java.io.IOException;

public class FileReaderDemo2 {

public static void main(String[] args) throws IOException {

FileReader fr = new FileReader("demo.txt");

/*

* 使用read(char[])读取文本文件数据。

* 先创建字符数组。

*/

char[] buf = new char[1024];

int len = 0;

while((len=fr.read(buf))!=-1){

System.out.println(new String(buf,0,len));

}

fr.close();

}

}

完整代码

public class FileWriterDemo {

public static void main(String[] args) throws IOException {

FileReader fr = null;

try {

fr = new FileReader("c:\test.txt");

char[] buf = new char[1024];

int len = 0;

while ((len = fr.read(buf)) != -1) {

System.out.println(new String(buf, 0, len));

}

} catch (IOException e) {

System.out.println("read-Exception :" + e.toString());

} finally {

if (fr != null) {

try {

fr.close();

} catch (IOException e) {

System.out.println("close-Exception :" + e.toString());

}

}

}

}

}

注意:

定义文件路径时,可以用“/”或者“\”。

在创建一个文件时,如果目录下有同名文

件将被覆盖。

在读取文件时,必须保证该文件已存在,

否则出异常。

练习:将D的文件复制到E盘

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

//练习:将D的文件复制到E盘

//第一种  一个一个的读

public class CopyText {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

FileReader fr = new FileReader("D:\1.txt");

FileWriter fw = new FileWriter("e:\2.txt");

int ch = 0;

while ((ch = fr.read()) != -1) {

fw.write(ch);

}

fr.close();

fw.close();

}

}

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

//第二种 一次读多个放到数组里面

//练习:将D的文件复制到E盘

public class CopyText {

private static final int BUFFER_SIZE = 1024;

public static void main(String[] args) throws IOException {

FileReader fr = null;

FileWriter fw = null;

try {

fr = new FileReader("D:\1.txt");

fw = new FileWriter("e:\2.doc");

char[] buf=new char[BUFFER_SIZE];//缓冲区 创建一个临时容器,用于缓存读取到的字符

int len=0;

while((len=fr.read(buf))!=-1){fw.write(buf, 0, len);}

} catch (Exception e) {

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();

}

}

}

}

}

五、字符流的缓冲区

缓冲区的出现提高了对数据的读写效率

对应类: BufferWriter  BufferReader

缓冲区要结合流才可以使用,是在流的就出上对流的功能进行了增强。

1、BufferReader举例:

import java.io.FileReader;

import java.io.BufferedReader;

import java.io.IOException;

public class CopyText {

public static void main(String[] args) throws IOException {

FileReader fr=new FileReader("D:\1.txt");

BufferedReader bufr=new BufferedReader(fr);

String line=null;

while((line=bufr.readLine())!=null)

System.out.println(line);

bufr.close();

}

}

2、BufferedWriter写入举例:

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");

IO总结

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

FileWriter fw = new FileWriter("buf.txt");

//为了提高写入效率,使用字符流的缓冲区,创建了一个字符写入流的缓冲区对象,并额指定要缓冲的流对象相关联

BufferedWriter bufw = new BufferedWriter(fw);

for (int i = 0; i < 4; i++) {

bufw.write("asdfghjk" + i);

bufw.newLine();

bufw.flush();

}

bufw.close();

}

}

练习:利用BufferedReader和BufferedWriter复制文件

import java.io.*;

public class CopyTextByBufTest {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

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();

}

}

六、装饰者模式

对原有类进行了功能的改变,增强。

例:

public class PersonDemo {

public static void main(String[] args) {

Person p = new Person();

p.chiFan();

NewPerson p1 = new NewPerson(p);

p1.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("甜点");

}

}

利用LineNumberReader装饰类设置行号。

import java.io.*;

public class LineNumberReaderDemo {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

FileReader fr = new FileReader("buf.txt");

LineNumberReader lnr = new LineNumberReader(fr);

String line = null;

lnr.setLineNumber(100);

while ((line = lnr.readLine()) != null) {

System.out.println(lnr.getLineNumber() + ":" + line);

}

lnr.close();

}

}

七、字节流

基本操作与字符流相同,但是它不仅可以操作字符,还可以操作其他媒体文件

FileInputStream 读取流 ,FileOutputStream 输出流。

1、读取流举例:

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.FileNotFoundException;

public class ByteStreamDemo {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

demo_read();

}

static void demo_read() throws IOException {

FileInputStream fis = new FileInputStream("IO.txt");

System.out.println(fis.available());

//第一种读取方式

byte[] buf = new byte[fis.available()];

fis.read(buf);

System.out.println(new String(buf));

//第二种读取方式,建议使用这种

byte[] buf1=new byte[1024];

int len=0;

while((len=fis.read(buf1))!=-1)

{

System.out.print(new String(buf1,0,len));

}

//第三种,一个字节的读

/*     int ch=0;

while((ch=fis.read())!=-1)

{

System.out.print((char)ch);

}*/

fis.close();

}

}

2、FileOutputStream 输出流举例

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.FileNotFoundException;

public class ByteStreamDemo {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

//demo_read();

demo_write();

}

public static void demo_write() throws IOException {

//1,创建字节输出流对象。用于操作文件.如果没有就创建新的文件

FileOutputStream fos = new FileOutputStream("bytedemo.txt");

//2,写数据。直接写入到了目的地中。

fos.write("abcdefg".getBytes());

fos.close();//关闭资源动作要完成。

}

}

八、字节流的缓冲区

同样是提高了字节流的读写效率。

BufferedInputStream和BufferedOutputStream

几种读取文件的效率举例:

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

public class CopyMp3Test {

public static void main(String[] args) throws IOException {

copy_4();

}

//     千万不要用,效率没有!

public static void copy_4() throws IOException {

FileInputStream fis = new FileInputStream("c:\\0.mp3");

FileOutputStream fos = new FileOutputStream("c:\\4.mp3");

int ch = 0;

while((ch =fis.read())!=-1){

fos.write(ch);

}

fos.close();

fis.close();

}

//不建议。

public static void copy_3() throws IOException {

FileInputStream fis = new FileInputStream("c:\\0.mp3");

FileOutputStream fos = new FileOutputStream("c:\\3.mp3");

byte[] buf = new byte[fis.available()];

fis.read(buf);

fos.write(buf);

fos.close();

fis.close();

}

public static void copy_2() throws IOException {

FileInputStream fis = new FileInputStream("c:\\0.mp3");

BufferedInputStream bufis = new BufferedInputStream(fis);

FileOutputStream fos = new FileOutputStream("c:\\2.mp3");

BufferedOutputStream bufos = new BufferedOutputStream(fos);

int ch = 0;

while((ch=bufis.read())!=-1){

bufos.write(ch);

}

bufos.close();

bufis.close();

}

public static void copy_1() throws IOException {

FileInputStream fis = new FileInputStream("c:\\0.mp3");

FileOutputStream fos = new FileOutputStream("c:\\1.mp3");

byte[] buf = new byte[1024];

int len = 0;

while((len=fis.read(buf))!=-1){

fos.write(buf,0,len);

}

fos.close();

fis.close();

}

}

九、转换流

InputStreamReader :字节到字符的桥梁。解码。

OutputStreamWriter:字符到字节的桥梁。编码。

转换流的由来:1、字符流与字节流之间的桥梁。2、方便了字符流与字节流之间的操作

转换流的应用:字节流中的数据都是字符时,转成字符流操作更高效。

例:获取键盘输入的字符

import java.io.IOException;

import java.io.InputStream;

public class ReadKey {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

StringBuilder sb = new StringBuilder();

InputStream in = System.in;

int ch = 0;

//read()方法是阻塞式方法

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 {

sb.append((char) ch);

}

}

}

}

例2:利用转换流实现读取键盘的操作,一次读取一行。

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 {

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();

}

}

}

例2的简化版:

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

public class TransStreamDemo2 {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

BufferedReader bufr = new BufferedReader(new InputStreamReader(

System.in));

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(

System.out));

String line = null;

while ((line = bufr.readLine()) != null) {

if ("over".equals(line))

break;

bufw.write(line.toUpperCase());

bufw.newLine();

bufw.flush();

}

}

}

例3:将输入的字符,存到文件里。

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

public class TransStreamDemo2 {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

BufferedReader bufr = new BufferedReader(new InputStreamReader(

System.in));

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("buf.txt")));

String line = null;

while ((line = bufr.readLine()) != null) {

if ("over".equals(line))

break;

bufw.write(line.toUpperCase());

bufw.newLine();

bufw.flush();

}

bufw.close();

}

}

例3:将文件中的字符读取到控制台

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

public class TransStreamDemo2 {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("buf.txt")));

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

String line = null;

while ((line = bufr.readLine()) != null) {

if ("over".equals(line))

break;

bufw.write(line.toUpperCase());

bufw.newLine();

bufw.flush();

}

bufw.close();

}

}

例4:将一个文件中的内容复制到另一个文件中

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

public class TransStreamDemo2 {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("buf.txt")));

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("buf_Copy.txt")));

String line = null;

while ((line = bufr.readLine()) != null) {

if ("over".equals(line))

break;

bufw.write(line.toUpperCase());

bufw.newLine();

bufw.flush();

}

bufw.close();

}

}

九、字符编码

字符流的出现为了方便操作字符。

更重要是的加入了编码转换。

通过子类转换流来完成。

• InputStreamReader

• OutputStreamWriter

在两个对象进行构造的时候可以加入字符

集。

常见的编码表:

1、ASCII:美国标准信息交换码。 用一个字节的7位可以表示。

2、ISO8859-1:拉丁码表,欧洲码表。用一个字节的8位表示。

3、GB2312:中国的中文编码表。

4、GBK:中国的中文编码表升级,融合了更多的中文文字符

号。

5、Unicode:国际标准码,融合了多种文字。 所有文字都用两个字节来表示,Java语言使用的就是unicode

7、UTF-8:最多用三个字节来表示一个字符。

转换流的编码应用:

1、可以将字符以指定编码格式存储。

2、可以对文本数据指定编码格式来解读。

3、指定编码表的动作由构造函数完成。

字符编码: 编码:字符串→字节数组  解码:字节数组→字符串

import java.io.FileInputStream;

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 {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

write_1();

writeText_2();

writeText_3();// UTF-8编码写入

readText_1();

readText_2();//用UTF-8编码读取GBK编码的文件

}

public static void readText_2() throws IOException {

InputStreamReader isr = new InputStreamReader(new FileInputStream(

"gbk_1.txt"), "utf-8");

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");

// 等同于FileWriter fw=new FileWriter("gbk_3.txt"); 系统默认是 GBK

/*

* 这两句代码的功能是等同的。 FileWriter:其实就是转换流指定了本机默认码表的体现。而且这个转换流的子类对象,可以方便操作文本文件。

* 简单说:操作文件的字节流+本机默认的编码表。 这是按照默认码表来操作文件的便捷类。

*

* 如果操作文本文件需要明确具体的编码。FileWriter就不行了。必须用转换流。

*/

osw.write("你好");

osw.close();

}

public static void write_1() throws IOException {

FileWriter fw = new FileWriter("gbk_1.txt");

fw.write("你好");

fw.close();

}

}

十、File类

1、用来将文件或者文件夹封装成对象

2、方便对文件与文件夹的属性信息进行操作。

3、File对象可以作为参数传递给流的构造函数。

4、了解File类中的常用方法。

例:初始化File类的几种方式

import java.io.File;

public class FileDemo {

public static void main(String[] args) {

// TODO Auto-generated method stub

constructorDemo();

}

public static void constructorDemo()

{

File f1=new File("D:\\1.txt");

System.out.println(f1.exists());

File f2=new File("D:\\","1.txt");

System.out.println(f2.exists());

File f3=new File("D:\\");

File f4=new File(f3,"a.txt");

System.out.println(f4.exists());

File f5=new File("D:"+File.separator+"1.txt");

System.out.println(f5);

}

}

File类常用的方法举例:

import java.io.File;

import java.io.IOException;

import java.text.DateFormat;

import java.util.Date;

public class FileMethodDemo {

public static void main(String[] args) {

/*

* File对象的常见方法。

*

* 1,获取。 1.1 获取文件名称。 1.2 获取文件路径。 1.3 获取文件大小。 1.4 获取文件修改时间。

*

* 2,创建与删除。

*

* 3,判断。

*

* 4, 重命名

*/

getDemo();

// createAndDeleteDemo();

// isDemo();

// renameToDemo();

// listRootsDemo();

}

输出结果:

parent:null

name:C:\Users\WH\Workspaces\MyEclipse Professional 2014\Test\IO.txt

path:IO.txt

len:8543

time:1470094643508

str_time:2016年8月2日 上午07时37分23秒

private static void getDemo() {

// TODO Auto-generated method stub

File file = new File("IO.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:" + absPath);

System.out.println("path:" + path);

System.out.println("len:" + len);

System.out.println("time:" + time);

System.out.println("str_time:" + str_time);

}

}

private static void createAndDeleteDemo() {

//创建单级文件夹

输出结果:

false

true

true

File dir = new File("D:\\abc");

boolean b = dir.mkdir();

System.out.println(b);

System.out.println(dir.delete());

//创建多级文件夹

File dir1=new File("D:\\sds\\ds\\adsa\\sa\\as\\a");

dir1.mkdirs();

System.out.println(dir1.delete());//虽然输出结果True,但只能删除最底层的文件夹

}

public static void isDemo() throws IOException{

File f = new File("aaa");

输出结果:

b=true

true

false

f.createNewFile();

boolean b = f.exists();

System.out.println("b="+b);

// 最好先判断是否存在。

System.out.println(f.isFile());

System.out.println(f.isDirectory());

输出结果:getFreeSpace:419413291008

getTotalSpace:429492695040

getUsableSpace:419413291008

C:\

D:\

E:\

H:\

}

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 file1 : files){

System.out.println(file1);

}

}

public static void renameToDemo() {

File f1 = new File("c:\\9.mp3");

File f2 = new File("d:\\aa.mp3");

boolean b = f1.renameTo(f2);//将f1的文件重命名为f2的文件名

System.out.println("b="+b);

}

FileFilter应用举例:

import java.io.File;

import java.io.FileFilter;

public class FilterByHidden implements FileFilter {

public boolean accept(File pathname) {

return !pathname.isHidden();

}

}

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);

}

}

import java.io.File;

public class FistListDemo {

public static void main(String[] args) {

// TODO Auto-generated method stub

listDemo();

listDemo_2();

listDemo_3();

listDemo_4();

}

/**

* 查找C下不是隐藏的文件

*/

public static void listDemo_3() {

File dir = new File("c:\\");

File[] files = dir.listFiles(new FilterByHidden());

for(File file : files){

System.out.println(file);

}

}

/**

* 查找D盘下所有的文件和文件夹

*/

public static void listDemo() {

/*

* 获取当前目录下的文件以及文件夹的名称,包含隐藏文件。 调用list方法的File对象中封装的必须是目录。

* 否则会发生NullPointerException 如果访问的系统级目录也会发生空指针异常。

* 如果目录存在但是没有内容,会返回一个数组,但是长度为0.

*/

File file = new File("D:\\");

String[] names = file.list();

System.out.println(names.length);

for (String name : names) {

System.out.println(name);

}

}

/**

* 筛选出后缀为.txt的文件

*/

public static void listDemo_2() {

File dir = new File("D:\\");

String[] names = dir.list(new SuffixFilter(".txt"));

for (String name : names) {

System.out.println(name);

}

}

/**

* FileFilter 过滤文件:先遍历,找符合条件的再放到数组中输出出来

*/

public static void listDemo_4() {

File dir = new File("D:\\");

String[] names = dir.list(new FilterByJava());

for (String name : names) {

System.out.println(name);

}

}

}

十一、递归:函数自己调用自己。

注意:递归时一定要明确结束条件。

应用场景: 当某一功能要重复使用时。

注意:

* 1,递归一定明确条件。否则容易栈溢出。

* 2,注意一下递归的次数。

例:读取文件夹下的所有文件

import java.io.File;

public class FileTest {

public static void main(String[] args) {

// TODO Auto-generated method stub

File dir = new File("D:");

listAll(dir, 0);

}

public static void listAll(File dir, int level) {

System.out.println(getSpace(level) + dir.getName());

// 获取指定目录下当前的所有文件夹或者文件对象。

level++;

File[] files = dir.listFiles();

for (int x = 0; x < files.length; x++) {

if (files[x].isDirectory()) {

listAll(files[x], level);

} else

System.out.println(getSpace(level) + files[x].getName());

}

}

private static String getSpace(int level) {

StringBuilder sb = new StringBuilder();

sb.append("|--");

for (int x = 0; x < level; x++) {

sb.insert(0, "|  ");

}

return sb.toString();

}

}

例:递归删除文件夹下所有的文件和文件夹

import java.io.File;

public class RemoveDirTest {

public static void main(String[] args) {

// TODO Auto-generated method stub

File dir = new File("D:\\脚本复制\\ewwe");

dir.delete();

removeDir(dir);

}

public static void removeDir(File dir) {

File[] files = dir.listFiles();

for (File file : files) {

if (file.isDirectory()) {

removeDir(file);

} else {

System.out.println(file + ":" + file.delete());

}

}

System.out.println(dir+":"+dir.delete());

}

}

例:递归举例,计算数的和

public class DiGuiDemo {

/**

* @param args

*/

public static void main(String[] args) {

/*

* 递归:

* 函数自身直接或者间接的调用到了自身。

* 一个功能在被重复使用,并每次使用时,参与运算的结果和上一次调用有关。

* 这时可以用递归来解决问题。

* 注意:

* 1,递归一定明确条件。否则容易栈溢出。

* 2,注意一下递归的次数。

*/

int sum = getSum(9000);

System.out.println(sum);

}

public static int getSum(int num){

int x = 9;

if(num==1)

return 1;

return num+getSum(num-1);

}

}

十二、Properties集合

特点:

1,该集合中的键和值都是字符串类型。

2,集合中的数据可以保存到流中,或者从流获取。

通常该集合用于操作以键值对形式存在的配置文件。

例:

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.PrintStream;

import java.util.Properties;

import java.util.Set;

/*

* Map

*         |--Hashtable

*                  |--Properties:

* Properties集合:

* 特点:

* 1,该集合中的键和值都是字符串类型。

* 2,集合中的数据可以保存到流中,或者从流获取。

*

* 通常该集合用于操作以键值对形式存在的配置文件。

*/

public class PropertiesDemo {

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

PropertiesUpDateAndAdd();

methodDemo_2();

methodDemo_3();

methodDemo_4();

PropertiesReadAndUpdate();

}

/**

* 对已有的配置文件中的信息进行修改。 思路:读取这个文件。 并将这个文件中的键值数据存储到集合中。 在通过集合对数据进行修改。

* 在通过流将修改后的数据存储到文件中。

* @throws IOException

*/

public static void PropertiesReadAndUpdate() throws IOException {

File file = new File("info.txt");

if (!file.exists()) {

file.createNewFile();

}

FileReader fr = new FileReader(file);

// 创建集合存储配置信息

Properties prop = new Properties();

// 将流中信息存储到集合中。

prop.load(fr);

prop.setProperty("wangwu", "16");

FileWriter fw = new FileWriter(file);

prop.store(fw, "");

prop.list(System.out);

fw.close();

fr.close();

}

/**

* 读取保存到本地的Properties文件

* @throws IOException

*/

public static void methodDemo_4() throws IOException {

Properties prop = new Properties();

// 集合中的数据来自于一个文件。

// 注意;必须要保证该文件中的数据是键值对。需要使用到读取流。

FileInputStream fis = new FileInputStream("info.txt");

// load方法

prop.load(fis);

prop.list(System.out);

}

/**

* 集合中的字符串键值信息持久化存储到文件中

* @throws IOException

*/

public static void methodDemo_3() throws IOException {

Properties prop = new Properties();

// 存储元素。

prop.setProperty("zhangsan", "30");

prop.setProperty("lisi", "31");

prop.setProperty("wangwu", "36");

prop.setProperty("zhaoliu", "20");

// 想要将这些集合中的字符串键值信息持久化存储到文件中。需要关联输出流。

FileOutputStream fos = new FileOutputStream("info.txt");

prop.store(fos, "info");

fos.close();

}

/**

* 演示Properties集合和流对象相结合的功能。

*/

public static void methodDemo_2() {

Properties prop = System.getProperties();

prop.list(System.out);

}

/**

* Properties集合的修改和增加

*/

public static void PropertiesUpDateAndAdd() {

Properties prop = new Properties();

// 存储元素

prop.setProperty("张三", "30");

prop.setProperty("lisi", "31");

prop.setProperty("wangwu", "36");

prop.setProperty("zhaoliu", "20");

// 修改元素

prop.setProperty("wangwu", "26");

Set names = prop.stringPropertyNames();

for (String name : names) {

String value = prop.getProperty(name);

System.out.println(name + ":" + value);

}

}

}

练习:定义功能,获取一个应用程序运行的次数,如果超过5次,给出使用次数已到请注册的提示。并不要在运行程序。

思路:

1,应该有计数器。

每次程序启动都需要计数一次,并且是在原有的次数上进行计数。

2,计数器就是一个变量。 突然冒出一想法,程序启动时候进行计数,计数器必须存在于内存并进行运算。

可是程序一结束,计数器消失了。那么再次启动该程序,计数器又重新被初始化了。

而我们需要多次启动同一个应用程序,使用的是同一个计数器。

这就需要计数器的生命周期变长,从内存存储到硬盘文件中。

3,如何使用这个计数器呢?

首先,程序启动时,应该先读取这个用于记录计数器信息的配置文件。

获取上一次计数器次数。 并进行试用次数的判断。

其次,对该次数进行自增,并自增后的次数重新存储到配置文件中。

4,文件中的信息该如何进行存储并体现。

直接存储次数值可以,但是不明确该数据的含义。 所以起名字就变得很重要。

这就有了名字和值的对应,所以可以使用键值对。

可是映射关系map集合搞定,又需要读取硬盘上的数据,所以map+io = Properties.

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.Properties;

public class PropertiesTest {

public static void main(String[] args) throws IOException {

getAppCount();

}

/**

* @throws IOException

*/

public static void getAppCount() throws IOException {

File conFile = new File("count.properties");

if (!conFile.exists()) {

conFile.createNewFile();

}

FileInputStream fis = new FileInputStream(conFile);

Properties prop = new Properties();

prop.load(fis);

String value = prop.getProperty("time");

int count = 0;

if (value != null) {

count = Integer.parseInt(value);

if (count >= 5) {

throw new RuntimeException("使用次数已到,请注册,给钱!");

}

}

count++;

//将改变后的次数重新存储到集合中

prop.setProperty("time", count+"");

FileOutputStream fos=new FileOutputStream(conFile);

prop.store(fos, "count");

fos.close();

fis.close();

}

}

练习: 获取指定目录下,指定扩展名的文件(包含子目录中的)

这些文件的绝对路径写入到一个文本文件中。简单说,就是建立一个指定扩展名的文件的列表。  思路:

1,必须进行深度遍历。

2,要在遍历的过程中进行过滤。将符合条件的内容都存储到容器中。

3,对容器中的内容进行遍历并将绝对路径写入到文件中。

package Test23;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileWriter;

import java.io.FilenameFilter;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

public class Test {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

File dir = new File("C:\\Users\\WH\\Workspaces\\MyEclipse Professional 2014\\Test");

FilenameFilter filter = new FilenameFilter() {

@Override

public boolean accept(File dir, String name) {

return name.endsWith(".java");

}

};

List list = new ArrayList();

getFiles(dir, filter, list);

File destFile = new File(dir, "javalist.txt");

write2File(list, destFile);

}

/**

* 对指定目录中的内容进行深度遍历,并按照指定过滤器,进行过滤, 将过滤后的内容存储到指定容器List中。

* @param dir

* @param filter

* @param list

*/

public static void getFiles(File dir, FilenameFilter filter, List list) {

File[] files = dir.listFiles();

for (File file : files) {

if (file.isDirectory()) {

// 递归啦!

getFiles(file, filter, list);

} else {

// 对遍历到的文件进行过滤器的过滤。将符合条件File对象,存储到List集合中。

if (filter.accept(dir, file.getName())) {

list.add(file);

}

}

}

}

public static void write2File(List list, File destFile)

throws IOException {

BufferedWriter bufw = null;

try {

bufw = new BufferedWriter(new FileWriter(destFile));

for (File file : list) {

bufw.write(file.getAbsolutePath());

bufw.newLine();

bufw.flush();

}

}

finally {

if (bufw != null)

try {

bufw.close();

} catch (IOException e) {

throw new RuntimeException("关闭失败");

}

}

}

}

总结:流的操作规律:

之所以要弄清楚这个规律,是因为流对象太多,开发时不知道用哪个对象合适。

想要知道开发时用到哪些对象。只要通过四个明确即可。

1,明确源和目的(汇)

源:InputStream  Reader

目的:OutputStream  Writer

2,明确数据是否是纯文本数据。

源:是纯文本:Reader

否:InputStream

目的:是纯文本 Writer

否:OutputStream

到这里,就可以明确需求中具体要使用哪个体系。

3,明确具体的设备。

源设备:

硬盘:File

键盘:System.in

内存:数组

网络:Socket流

目的设备:

硬盘:File

控制台:System.out

内存:数组

网络:Socket流

4,是否需要其他额外功能。

1,是否需要高效(缓冲区);

是,就加上buffer.

2,转换。

需求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,一旦操作文本涉及到具体的指定编码表时,必须使用转换流 。

十三、IO包中的其他类

打印流

• PrintWriter与PrintStream

• 可以直接操作输入流和文件。

PrintStream:

1,提供了打印方法可以对多种数据类型值进行打印。并保持数据的表示形式。

2,它不抛IOException.

构造函数,接收三种类型的值:

* 1,字符串路径。

* 2,File对象。

* 3,字节输出流。

例:

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.PrintStream;

public class PrintStreamDemo {

public static void main(String[] args) throws IOException {

PrintStream out = new PrintStream("print.txt");

//              int by = read();

//              write(by);

//              out.write(610);//只写最低8位,

//              out.print(97);//将97先变成字符保持原样将数据打印到目的地。

out.close();

}

}

PrintWriter:字符打印流。

构造函数参数:

1,字符串路径。

2,File对象。

3,字节输出流。

4,字符输出流。

例:

import java.io.BufferedReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

public class PrintWriterDemo {

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

PrintWriter out = new PrintWriter(new FileWriter("out.txt"),true);

String line =  null;

while((line=bufr.readLine())!=null){

if("over".equals(line))

break;

out.println(line.toUpperCase());

//                       out.flush();

}

out.close();

bufr.close();

}

}

序列流

• SequenceInputStream

• 对多个流进行合并。

例:

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.SequenceInputStream;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Enumeration;

import java.util.Iterator;

public class SequenceInputStreamDemo {

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

/*

* 需求:将1.txt 2.txt 3.txt文件中的数据合并到一个文件中。

*/

ArrayList al = new ArrayList();

for(int x=1; x<=3; x++){

al.add(new FileInputStream(x+".txt"));

}

Enumeration en = Collections.enumeration(al);

SequenceInputStream sis = new SequenceInputStream(en);

FileOutputStream fos = new FileOutputStream("1234.txt");

byte[] buf = new byte[1024];

int len = 0;

while((len=sis.read(buf))!=-1){

fos.write(buf,0,len);

}

fos.close();

sis.close();

}

}

切割文件举例:

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.Properties;

public class SplitFileDemo {

private static final int SIZE = 1024 * 1024;

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

File file = new File("D:\\重庆测试数据.zip");

splitFile(file);

}

private static void splitFile(File file) throws IOException {

FileInputStream fis = new FileInputStream(file);

byte[] buf = new byte[SIZE];

FileOutputStream fos = null;

int len = 0;

int count = 1;

/*

* 切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数。 以方便于合并。

* 这个信息为了进行描述,使用键值对的方式。用到了properties对象

*

*/

Properties prop = new Properties();

File dirFile = new File("D:\\partFiles");

if (!dirFile.exists())

dirFile.mkdir();

while ((len=fis.read(buf))!=-1) {

fos=new FileOutputStream(new File(dirFile,(count++)+".part"));

fos.write(buf,0,len);

fos.close();

}

prop.setProperty("partCount", count+"");

prop.setProperty("fileName", file.getName());

fos=new FileOutputStream(new File(dirFile,count+".properties"));

prop.store(fos, "Save file Info");

fos.close();fis.close();

}

}

将切割的文件合并,合并信息从配置文件中获取:

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.SequenceInputStream;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Enumeration;

import java.util.Properties;

public class MergerFile {

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

File dir = new File("D:\\partFiles");

mergeFile_2(dir);

}

public static void mergeFile_2(File dir) throws IOException {

// 获取指定目录下的配置文件对象。

File[] files = dir.listFiles(new SuffixFilter(".properties"));

if (files.length != 1)

throw new RuntimeException(dir + ",该目录下没有Properties扩展名的文件或者不唯一");

//记录文件对象。

File conFile=files[0];

//获取该文件中的信息

Properties properties=new Properties();

FileInputStream fis=new FileInputStream(conFile);

properties.load(fis);

String fileName=properties.getProperty("fileName");

int count=Integer.parseInt(properties.getProperty("partCount"));

//获取该目录下的所有碎片文件。

File[] partFiles=dir.listFiles(new SuffixFilter(".part"));

if (partFiles.length!=(count-1)){

throw new RuntimeException("碎片文件不符合要求,个数不对!应该"+count+"个");

}

ArrayList a1=new ArrayList();

for (int i = 0; i < partFiles.length; i++) {

a1.add(new FileInputStream(partFiles[i]));

}

Enumeration en=Collections.enumeration(a1);

SequenceInputStream sisStream=new SequenceInputStream(en);

FileOutputStream fos=new FileOutputStream(new File(dir,fileName));

byte[] buf=new byte[1024];

int len=0;

while((len=sisStream.read(buf))!=-1)

{

fos.write(buf,0,len);

}

fos.close();

sisStream.close();

}

}

操作对象

• ObjectInputStream与ObjectOutputStream

• 被操作的对象需要实现Serializable (标记接口);

Java 数据结构

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spark基础学习笔记01:初步了解Spark
下一篇:《Python大规模机器学习》 —1.2.6科学计算发行版
相关文章