字节流
OutputStream
InputStream
基本操作与字符流类相同。
特点演示:
import java.io.*;
class Demo1FileStream {
public static void main(String[] args) throws IOException {
FileOutputStream ops = new FileOutputStream("out.txt"); //创建字节输出对象
ops.write("abc".getBytes()); //把字符串转换成字节型,再写入
ops.close();
userReader_1();
System.out.println("------------------------");
userReader_2();
System.out.println("------------------------");
userReader_3();
}
public static void userReader_1() throws IOException {
FileInputStream fis = new FileInputStream("out.txt");//创建一个字符输入流对象
//使用read()方法一次读取一个字节
int num = 0;
while((num = fis.read()) != -1) {
System.out.println((char)num);
}
fis.close();
}
public static void userReader_2() throws IOException {
FileInputStream fis = new FileInputStream("out.txt");
byte[] buf = new byte[1024]; //定义一个数组
int len = 0;
while((len = fis.read(buf)) != -1) { //把字节存入数组
System.out.println(new String(buf,0,len));
}
fis.close();
}
public static void userReader_3() throws IOException {
FileInputStream fis = new FileInputStream("out.txt"); //创建字节输入流对象
byte[] buf = new byte[fis.available()]; //available()可以打印文件里面字节大小,当文件太大时不能使用,因为默认的内存不够
fis.read(buf);
System.out.println(new String(buf));
}
}
字节流缓冲区
同样是提高了字节流的读写效率BufferedOutputStream、BufferedInputStream
演示mp3的复制,通过缓冲区
import java.io.*;
class Test2CopyMp3 {
public static void main(String[] args) {
// 创建字节流缓冲区引用
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//创建字节流缓冲区对象,并把字节流对象传入
bis = new BufferedInputStream(new FileInputStream("C:\\Users\\Loppz\\Documents\\Tongbu\\Ringtone\\Minions Hello!.mp3"));
bos = new BufferedOutputStream(new FileOutputStream("C:\\Users\\Loppz\\Documents\\Tongbu\\Ringtone\\Minions.mp3"));
//读取数据并写入数据
int num = 0;
while((num = bis.read()) != -1) {
bos.write(num);
}
}
catch(IOException e) {
}
finally{
if(bis != null) {
try {
bis.close();
}
catch(IOException e) {
}
}
if(bos != null) {
try {
bis.close();
}
catch(IOException e) {
}
}
}
}
}
缓冲区中无非就是封装了一个数组,并对外提供了更多的方法对数组进行访问,其实这些方法最终操作的都是数组的角标。
原理:
其实就是从源中获取一批数据到缓冲区中,再从缓冲区中不断地取出一个一个数据,在此次取完后,再从源中继续取一批数据进缓冲区,当源中的数据取完时,用-1作为结束标记。
import java.io.*;
class UserBufferedInputStream {
private InputStream in; //定义一个InputStream类的引用
private int pos = 0,count = 0; //定义两个变量pos用于操作数组中的元素,count记录缓冲区数据个数
private byte[] buf = new byte[1024*4]; //定义一个数组作为缓冲区
UserBufferedInputStream(InputStream in) {
this.in = in;
}
//一次读一个字节,从缓冲区(字节数组)获取。
public int userRead() throws IOException {
//从源中获取一批数据到缓冲区中,需要先做判断,只有计数器为0时,才需要从源 中获取数据
if(count == 0 ) {
count = in.read(buf);
if(count < 0)
return -1;
pos = 0;
byte b = buf[pos]; //获取缓冲区的数据
count--; //没获取完一次里面的数据就少一个,所以count--
pos++; //依次获取后面的数据
return b&255; //保留有效位
}
//如果count大于0就直接获取缓冲区里面的数据了
else if(count > 0) {
byte b = buf[pos];
count--;
pos++;
return b&0xff;
}
return -1;
}
public void myClose()throws IOException
{
in.close();
}
}
转换流
读取键盘录入
System.out:对应的是标准输出设备,控制台。
System.in:对应的标准输入设备:键盘。
通过键盘录入数据,当录入一行数据后,就将该行数据进行打印,如果录入的数据是over,那么停止录入。
import java.io.*;
class Demo3ReadIN {
public static void main(String[] args) throws IOException {
InputStream is = System.in; //创建一个键盘录入对象
StringBuilder sb = new StringBuilder(); //创建一个StringBuild对象,来缓冲键盘录入的数据
while(true) {
int num = is.read();
if(num == '\r') //键盘录入时候会有\r\n回车符,因此进行判断
continue;
if(num == '\n') {
String s = sb.toString();
if("over".equals(s))
break;
System.out.println(s);
sb.delete(0, sb.length());
} else {
sb.append((char)num);
}
}
}
}
转换流
字符流与字节流之间的桥梁,方便了字符流与字节流之间的操作。
InputStreamReader:字节到字符的桥梁
OutputStreamReader:字符到字节的桥梁
利用转换流,让键盘录入使用readLine()方法
import java.io.*;
class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
//获取键盘录入对象。
//InputStream in = System.in;
//将字节流对象转成字符流对象,使用转换流。InputStreamReader
//InputStreamReader isr = new InputStreamReader(in);
//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
//BufferedReader bufr = new BufferedReader(isr);
//键盘的最常见写法,这时简化上述代码后的写法
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
// OutputStream out = System.out; //System.out返回的类型是PrintStream,是OouPutStream子类
// OutputStreamWriter osw = new OutputStreamWriter(out);
// BufferedWriter bufw = new BufferedWriter(osw);
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();
}
bufr.close();
}
}
字符流与字节流的最大区别
Ì使用字节流读取一个中文字符需要读取两次,一个字符由两个字节而成,使用字符流只需一次。
流的操作规律
通过三个明确来完成,到底用哪个对象
1,明确源和目的。
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer。
2,操作的数据是否是纯文本。
是:字符流。
不是:字节流。
3,当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘。键盘
目的设备:内存,硬盘,控制台。
1,明确源和目的。
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer。
2,操作的数据是否是纯文本。
是:字符流。
不是:字节流。
3,当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘。键盘
目的设备:内存,硬盘,控制台。
例如:
1、将一个文本文件中数据存储到另一个文件中,复制文件。
源:因为是源,所以使用读取流。InputStream Reader
是不是操作文本文件。
是!这时就可以选择Reader
这样体系就明确了。
接下来明确要使用该体系中的哪个对象。
明确设备:硬盘。上一个文件。
Reader体系中可以操作文件的对象是 FileReader
是不是操作文本文件。
是!这时就可以选择Reader
这样体系就明确了。
接下来明确要使用该体系中的哪个对象。
明确设备:硬盘。上一个文件。
Reader体系中可以操作文件的对象是 FileReader
是否需要提高效率:是!。加入Reader体系中缓冲区 BufferedReader.
FileReader fr = new FileReader("a.txt");
BufferedReader bufr = new BufferedReader(fr);
目的:OutputStream Writer
是否是纯文本。
是!Writer。
设备:硬盘,一个文件。
Writer体系中可以操作文件的对象FileWriter。
是否需要提高效率:是!。加入Writer体系中缓冲区 BufferedWriter
FileWriter fw = new FileWriter("b.txt");
BufferedWriter bufw = new BufferedWriter(fw);
2、将键盘录入的数据保存到一个文件中。
这个需求中有源和目的都存在。
那么分别分析
源:InputStream Reader
是不是纯文本?是!Reader
设备:键盘。对应的对象是System.in.
不是选择Reader吗?System.in对应的不是字节流吗?为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。
所以既然明确了Reader,那么就将System.in转换成Reader。
用了Reader体系中转换流,InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
需要提高效率吗?需要!BufferedReader
BufferedReader bufr = new BufferedReader(isr);
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
FileWriter fw = new FileWriter("c.txt");
需要提高效率吗?需要。
BufferedWriter bufw = new BufferedWriter(fw);
那么分别分析
源:InputStream Reader
是不是纯文本?是!Reader
设备:键盘。对应的对象是System.in.
不是选择Reader吗?System.in对应的不是字节流吗?为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。
所以既然明确了Reader,那么就将System.in转换成Reader。
用了Reader体系中转换流,InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
需要提高效率吗?需要!BufferedReader
BufferedReader bufr = new BufferedReader(isr);
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
FileWriter fw = new FileWriter("c.txt");
需要提高效率吗?需要。
BufferedWriter bufw = new BufferedWriter(fw);
File类
File类用来将文件或者文件夹封装成对象,方便对文件夹的属性信息进行操作。
File对象可以作为参数传递给流的构造函数
常见方法
File类常见方法:
1,创建
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。
2,删除
boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();在程序退出时删除指定文件。
3,判断
boolean exists() :文件是否存在.
isFile():
isDirectory();
isHidden();
isAbsolute();
4,获取信息
getName(): 获取文件名称
getPath():获取文件路劲
getParent():看示例
getAbsolutePath() 获取文件的绝对路径
long lastModified()
long length()
1,创建
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。
2,删除
boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();在程序退出时删除指定文件。
3,判断
boolean exists() :文件是否存在.
isFile():
isDirectory();
isHidden();
isAbsolute();
4,获取信息
getName(): 获取文件名称
getPath():获取文件路劲
getParent():看示例
getAbsolutePath() 获取文件的绝对路径
long lastModified()
long length()
class Demo1File {
public static void main(String[] args) throws IOException {
Method_3();
}
public static void Method_3() throws IOException {
File f = new File("file.txt");
System.out.println(f.getPath());
System.out.println(f.getAbsolutePath());
}
public static void Method_2() throws IOException {
File f = new File("D:\\Material\\Java\\JavaRoom\\day06_IO\\file.txt");
System.out.println(f.exists()); //记住在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在。
System.out.println(f.isFile());
System.out.println(f.isDirectory());
System.out.println(f.isAbsolute());
}
public static void Method_1() throws IOException {
//将file.txt封装成file对象,可以将己有的和为出现的文件或者文件夹封装成对象
File f1 = new File("file.txt");
System.out.println(f1.createNewFile());
// System.out.println(f1.delete());
File f2 = new File("File");
System.out.println(f2.mkdir());
}
}
list()方法
File类里面的方法
listRoots():查询电脑有效的磁盘空间
list():获取指定目录下下的文件名,包括隐藏文件,里面封装的必须是目录,否则会产生NullPointerException异常,如果目录存在但是没内容,会返回一个 数组长度0.
list(FilenameFilter filter): 用来过滤指定的文件类型
listFile():类似于list()但是listFile()返回的是对象
import java.io.*;
class Demo2File {
public static void listRootsDemo() {
File[] files = File.listRoots(); //电脑有效的磁盘空间大小
for(File f:files) {
System.out.println(f);
}
}
public static void listDemo() {
File f = new File("D:\\Tools\\"); //获取D盘目录下Tools文件夹里的文件名
System.out.println(f.isDirectory());
String[] s = f.list();
for(String o: s){
System.out.println(o);
}
}
//获取指定目录下所有.java文件
public static void listTest() {
File f = new File("D:\\Material\\Java\\源代码\\day02");
//new FilenameFilter匿名内部类,重写accept方法,把不是.java文件过滤掉
String[] arr = f.list(new FilenameFilter() {
public boolean accept(File f,String name) {
return name.endsWith(".java");
}
});
for(String o:arr) {
System.out.println(o);
}
}
public static void main(String[] args) {
File f = new File("D:\\Tools");
System.out.println(f.exists());
System.out.println(f.isDirectory());
File[] files = f.listFiles(); //此方法返回的是对象,所以还可以进行相应的操作
for(File file : files) {
System.out.println(file.getName()+" "+file.length());
}
listTest();
}
}
递归
函数自身直接或者间接的调用到了自身。
一个功能在被重复使用,并每次使用时,参与运算的结果和上一次调用有关。这时可以用递归来解决问题
注意:
1,限定条件。
2,要注意递归的次数。尽量避免内存溢出。
2,要注意递归的次数。尽量避免内存溢出。
需求:列出指定目录下文件或者文件夹,包含子目录中的内容。
思路:
在列出过程中出现的还是目录的话,还可以再次调用本功能。只需定义一个获取功能的函数,这种方式用递归来完成。
class Demo3File {
public static void main(String[] args) {
File f = new File("C:\\Users\\Loppz\\Music\\iTunes");
getList(f);
}
public static void getList(File f) {
File[] files = f.listFiles(); //调用fistFiles方法返回一个数组
for(int x = 0 ; x < files.length ; x++) {
if(files[x].isDirectory()) //对遍历出的对象进行判断,如果是文件夹的话,则继续调用此函数
getList(files[x]);
else
System.out.println(files[x].getName());
}
}
}
利用递归求1-10的和:
class TestWork {
public static void main(String[] args) {
System.out.println(getSum(10));
}
public static int getSum(int num) {
if(num == 1)
return 1;
return num+getSum(num -1 );
}
}
需求:删除一个带内容的目录
在window中,删除目录从里面往外删除,就需要用到递归。
import java.io.*;
class Test1Remove {
public static void main(String[] args) {
File dir = new File("D:\\Meterial\\Java\\Demo");
removeDir(dir);
}
public static void removeDir(File dir) {
File[] files = dir.listFiles();
for(File file : files) {
if(file.isDirectory()) //判断是否是文件夹
removeDir(file); //是的话则再次调用方法
else
file.delete(); //不是的话则删除掉
}
dir.delete(); //删除最后的文件夹
}
}
Properties集合
Properties是hashtable的子类。
特点:
1. 该集合中的键和值都是字符串类型
2. 集合中的数据可以保存到流中,或者从流中获取
2. 集合中的数据可以保存到流中,或者从流中获取
3. 通常该集合用于操作以键值对形式存在的配置文件
常用方法演示:
import java.io.*;
class Demo4Properties {
public static void main(String[] args) {
setAndGet();
}
public static void setAndGet() {
Properties prop = new Properties();
prop.setProperty("Jack", "29");
prop.setProperty("Nacy", "28");
prop.setProperty("Jack", "41"); //setProperty方法既可以添加键值对,又可以修改。
// String value = prop.getProperty("Jack"); //获取jack的年龄
// System.out.println(value);
Set<String> names = prop.stringPropertyNames(); //调用stringPropertyNames()方法返回一个装有key的set集合
for(String name : names) {
System.out.println(name);
}
}
将流中的数据存储到集合中,假如有一个文件info.txt,里面的数据为key = value格式
思路:
1,用一个流和需要操作的文件文件关联。
2,读取一行数据,将该行数据用"="进行切割。
3,等号左边作为键,右边作为值。存入到Properties集合中即可。
1,用一个流和需要操作的文件文件关联。
2,读取一行数据,将该行数据用"="进行切割。
3,等号左边作为键,右边作为值。存入到Properties集合中即可。
import java.io.*;
import java.util.*;
class TestWork {
public static void main(String[] args) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("info.txt"));
Properties prop = new Properties();
String line = null;
while((line = br.readLine()) != null) {
String[] arr = line.split("=");
prop.setProperty(arr[0], arr[1]);
}
System.out.println(prop);
}
catch(IOException e) {
}
finally {
if(br != null) {
try {
br.close();
}
catch(IOException e) {
}
}
}
}
}
用Properties中特有的方法:
public static void loadDemo() throws IOException {
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("info.txt");
prop.load(fis); //把数据从输入流存入集合
FileOutputStream fos = new FileOutputStream("info.txt");
prop.store(fos, "aaaa"); //把集合中的数据存入输出流打印到本地
prop.list(System.out); //list集合方法列出集合中的数据
fos.close();
fis.close();
}
需求:限制程序运行次数。当运行次数到达5次时,给出,请您注册的提示。并不再让该程序执行。
思路:
1、建立一个配置文件,定义一个键值对用于记录该软件的使用次数。
2、把键值对通过输入流加载到Properties集合中,判断使用次数
3、如果使用次数已到,则给出提示,如果没到便让值+1通过输出流存入到配置文件
import java.io.*;
import java.util.*;
class Test3RunCount {
public static void main(String[] args) throws IOException {
Properties prop = new Properties();
//创建一个File对象,对其进行判断存不存在
File file = new File("count.ini");
if(!file.exists())
file.createNewFile();
FileInputStream fis = new FileInputStream(file);
prop.load(fis);
int count = 0; //定义一个变量用来记录次数
String value = prop.getProperty("time"); //通过time获取次数
if(value != null) { //判断是否为空,不是的话则执行下面的语句把字符串转换成int型
count = Integer.parseInt(value);
if(count > 5) { //限制使用次数
System.out.println("使用次数已到");
return;
}
}
count++; //使用一次加一次
prop.setProperty("time",count+""); //对键值对进行修改
FileOutputStream fos = new FileOutputStream(file);
prop.store(fos,"");
fos.close();
fis.close();
}
}
将一个指定目录下的java文件的绝对路径,存储到一个文本文件中,建立一个java文件列表文件。
思路:
1,对指定的目录进行递归。
2,获取递归过程所以的java文件的路径。
3,将这些路径存储到集合中。
4,将集合中的数据写入到一个文件中。
思路:
1,对指定的目录进行递归。
2,获取递归过程所以的java文件的路径。
3,将这些路径存储到集合中。
4,将集合中的数据写入到一个文件中。
import java.io.*;
import java.util.*;
class Test2FileList {
public static void main(String[] args) {
File file1 = new File("D:\\Material\\Java\\源代码");
List<file> list = new ArrayList<file>();
method(file1,list);
File file2 = new File(file1,"java.txt");
userWriter(list,file2.toString());
}
//顶一个函数接受File对象和数组
public static void method(File dir,List<File> list) {
File[] dirs = dir.listFiles();
//File数组进行遍历,判断是否是文件夹
for(File file : dirs) {
if(file.isDirectory()) //如果是则继续,调用方法
method(file,list);
else {
//如果不是则判断是不是.java文件,是就添加进集合
if(file.getName().endsWith(".java"))
list.add(file);
}
}
}
//定义一个函数用来接受,集合和要存储的文件名
public static void userWriter(List<File> list,String name) {
BufferedWriter buf = null;
try {
buf = new BufferedWriter(new FileWriter(name));
for(File f : list) {
String path = f.getAbsolutePath();
buf.write(path);
buf.newLine();
buf.flush();
}
}
catch(IOException e) {
}
finally {
if(buf != null){
try {
buf.close();
}
catch(IOException e) {
}
}
}
}
}</file></file>