Java基础---IO流(中)

时间:2023-02-16 13:45:06


IO流常用基类-字节流

示例 (获取用户键盘录入的数据并将数据变成大写显示在控制台,如果用户输入的是over,结束)

import java.io.IOException;
import java.io.InputStream;

public class ReadKey
{
public static void main(String[] args) throws IOException
{
readKey();
}

public static void readKey() throws IOException
{
//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);
}
}
}
}
Java基础---IO流(中)

转换流

特点:

1、是字节流和字符流之间的桥梁。

2、该流对象中可以对读取到的字节数据进行指定的编码转换。

什么时候使用?

1、当字节和字符之间有转换时。

2、流操作的数据需要进行编码表的制定时。

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

具体对象体现:

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

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

这两个流对象是字符流体系中的成员。

那么他们转换作用,而本身又不是字符流。所以在构造的时候,需要传入字节流对象进来。

构造函数:

InputStreamReader(InputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK

InputStreamReader(InputSteam,String charSet):通过该构造函数初始化,可以指定编码表。

OutputStreamWriter(OutputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK

OutputStreamWriter(OutputSteam,String charSet):通过该构造函数初始化,可以指定编码表。

操作文件的字符流对象是转换流的子类

Reader

     |--InputStreamReader

              |--FileReader

Writer

    |--OutputStreamWriter

             |--FileWriter

如果要使用指定的编码表时,必须使用转换流。

FileReader fr = new FileReader("a.txt");//操作a.txt的中的数据使用的本系统的默认的GBK.

InputSteamReader isr = new InputStreamReader(new FileInputStream("a.txt"));

这两句代码的意义相同。但如果a.txt中的文件的字符数据是通过utf-8的形式编码。那么在读取时,就必须指定编码表。那么转换流必须使用。

InputStreamReader isr = new InputreamReader(new FileInputStream("a.txt"),"utf-8");

示例1:(InputStreamReader是字节流通向字符流的桥梁)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
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);
/*简写
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
*/
String line = null;
//读取到了字符串数据
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
System.out.println(line.toUpperCase());
}

}
}

Java基础---IO流(中)

示例2:(OutputStreamReader是字符流通向字节流的桥梁)
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.OutputStream;
public class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//System.out的类型是PrintStream,属于OtputStream
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
//读取到了字符串数据
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
//将字符数据用缓冲区对象将数据写入缓冲区,目的地System.out
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}

}
}
Java基础---IO流(中)
示例3:(将键盘录入的数据写入到一个文件中)

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.OutputStream;
import java.io.FileOutputStream;
public class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt")));
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}

}
}
Java基础---IO流(中)

示例4:(将一个文本内容显示在控制台上)

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
public class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("a.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();
}
<span style="white-space:pre"></span>}
}
Java基础---IO流(中)

示例5:(将一个文本内容复制到另一个文件中)

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
public class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("a.txt")));
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();
}

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

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

1、明确源和目的

源:InputStream Readr

目的:OutputStream Writer

2、明确数据是否纯文本数据

源:是纯文本:Reader  否:InputStream

目的:是纯文本:Writer 否:OutputStream

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

3、明确具体的设备

源设备:硬盘 File、键盘 System.in、内存 数组、网络 Socket流 

目的设备:硬盘 File、控制台System.out、内存 数组、网络 Socket流

4、是否需要其它额外功能

是否需要高效(缓冲区):是,就加上buffer

需求1:复制一个文本文件

1、明确源和目的   源:InputStream Readr 目的: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 FileStreamWriter("b.txt"));

============================================================

需求2:读取键盘录入信息,并写入到一个文件中

1、明确源和目的   源:InputStream Readr 目的:OutputStream Writer

2、明确数据是否纯文本数据    源:是纯文本:Reader    目的:是纯文本:Writer 

3、明确具体的设备       源设备: 键盘 System.in      目的设备: File

FileReader fr = System.in;  FileWriter fw = new FileWriter("b.txt");

这样做可以完成,但是麻烦。将读取的字节数据转换成字符串,在由字符流操作

4、是否需要其它额外功能 

需要,转换。将字节流转换字符流,因为明确源是Reader,这样操作文本更快捷。

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 FileStreamWriter("b.txt"));

====================================================================

需求3:将一个文本数据显示在控制台上

1、明确源和目的   源:InputStream Readr 目的:OutputStream Writer

2、明确数据是否纯文本数据    源:是纯文本:Reader    目的:是纯文本:Writer 

3、明确具体的设备       源设备:File      目的设备: 控制台System.out

FileReader fr = new FileReader("a.txt");  FileWriter fw = System.out;

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

任何Java识别的字符数据都是Unicode码表,但是FileWriter写入本地文件使用的是本地编码,也就是GBK码表。而OutputStreamWriter可以使用指定的编码将要写入流中的字符编码成字节。

示例1:(UTF-8编码)

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
writeText();
}
public static void writeText() throws IOException
{
//下面这句代码等同于FileWriter fw = new FileWriter("b.txt")
//FileWriter其实就是转换流指定了本机默认码表的体现,而且这个转换流的子类对象,可以方便操作文本文件。
//简单说:操作文件的字节流+本机默认的编码表。
//这是按照默认码表来操作的便捷类
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"GBK");
//如果操作文本文件需要明确的具体码表,FileWriter就不行了,必须用转换流。
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");
osw.write("你好");
osw.close();
}
}
Java基础---IO流(中)

P.S.

UTF-8编码,一个中文三个字节
示例2:(UTF-8解码 打印d.txt(内容是采用utf-8编码的)文件中的内容)

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
public class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
writeText();
}
public static void writeText() throws IOException
{
//这里不能使用FileReader 因为d.txt文件中是由UTF-8编码的“你好”,6个字节。
//如果使用FileReader类是用GBK编码进行读取,6个字节代表3个字符 会乱码
InputStreamReader isr = new InputStreamReader(new FileInputStream("d.txt"),"UTF-8");

BufferedReader bufr = new BufferedReader(isr);

String line = null;
while((line = bufr.readLine())!=null)
{
System.out.println(line);
}
bufr.close();
}
}
Java基础---IO流(中)

Java基础---IO流(中)

File类

File类用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作。File对象可以作为参数传递给流的构造函数。

P.S.

流只能操作数据,不能操作文件。

示例1:

import java.io.File;
public class FileDemo
{
public static void main(String[] args)
{
constructorDemo();
}

public static void constructorDemo()
{
//可以将一个已经存在的,或者不存在的文件或者目录封装成file对象
//方式一
File f1 = new File("d:\\demo\\a.txt");
//方式二
File f2 = new File("d:\\demo","a.txt");
//方式三
File f = new File("d:\\demo");
File f3 = new File(f,"a.txt");
//考虑到Windows和Linux系统通用
File f4 = new File("d:"+File.separator+"demo"+File.separator+"a.txt");
}
}
P.S.

File.separator是与系统有关的默认名称分隔符。在UNIX系统上,此字段的值为‘/’;在Microsoft Windows系统上,它为‘\\’。

File对象的常用方法:

1、获取

getName():获取文件或者文件夹的名称。

getPath():File对象中封装的路径是什么,获取的就是什么。

getAbsolutePath():物流File对象中封装的路径是什么,获取的都是绝对路径。

getParent():获取File对象封装的文件或者文件夹的父目录。如果封装的是相对路径,那么返回null

long length():获取文件大小

long lastModified():获取文件或者文件最后一次修改的时间

static File[] listRoots():获取的是被系统中有效盘符

String[] list():获取指定目录下当前文件以及文件夹的名称。

String[] list(FilenameFilter):可以根据指定的过滤器,过滤后的文件及文件夹名称

File[] listFiles():获取指定目录下的文件以及文件夹对象

示例2:

import java.io.File;
import java.text.DateFormat;
import java.util.Date;
public class FileMethodDemo
{
public static void main(String[] args)
{
getDemo();
}
public static void getDemo()
{
File file1 = new File("a.txt");
File file2 = new File("d:\\demo\\a.txt");

String name = file2.getName();
String absPath = file2.getAbsolutePath();//绝对路径
String path1 = file1.getPath();
String path2 = file2.getPath();
long len = file2.length();
long time = file2.lastModified();
//相对路径不同,父目录不同
//如果此路径名没有指定的父目录,则返回null
String parent1 = file1.getParent();
String parent2 = file2.getParent();
Date date = new Date(time);
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
String str_time = df.format(date);

System.out.println("name:" + name);
System.out.println("absPath:" + absPath);
System.out.println("path1:" + path1);
System.out.println("path2:" + path2);
System.out.println("len:" + len);
System.out.println("str_time:" + str_time);
System.out.println("parent1:" + parent1);
System.out.println("parent2:" + parent2);
}
}
Java基础---IO流(中)

2、创建和删除

创建:

boolean createNewFile() throws IOException:创建文件,如果被创建的文件已经存在,则不创建

boolean mkdir():文件夹。

boolean mkdirs():创建多级文件夹。

删除:

boolean delete():可以删除文件或者文件夹。注意:对于文件夹只能删除不带内容的空文件夹,对带有内容的,不可以直接删除,必须要从里往外删除。

void deleteOnExit(): 删除动作交给系统完成,物流是否发生异常,系统在退出时执行删除动作

示例3:

import java.io.File;
import java.io.IOException;
public class FileMethodDemo
{
public static void main(String[] args) throws IOException
{
createAndDeleteDemo();
}
public static void createAndDeleteDemo() throws IOException
{
File file = new File("file.txt");
//和输出流不一样,如果文件不存在,则创建,如果文件存在,则不创建
boolean b1 = file.createNewFile();
System.out.println("b1="+b1);
//使用delete方法删除文件夹的时候,如果文件夹中有文件,则会删除失败
boolean b2 = file.delete();
System.out.println("b2="+b2);

File dir = new File("abc\\ab");
//使用mkdir可以创建多级目录
boolean b3 = dir.mkdir();//make directory
System.out.println("b3="+b3);

//最里层目录被干掉,dir代表的是最里的目录
boolean b4 = dir.delete();
System.out.println("b4="+b4);
}
}
Java基础---IO流(中)

3、判断

boolean exists():判断文件或者文件夹是否存在

boolean isFile():判断File对象中封装的是否是文件

boolean isDirectory():判断File对象封装的是否是文件夹

boolean isHidden():判断文件或者文件夹是否隐藏。

示例4:

import java.io.File;
import java.io.IOException;
public class FileMethodDemo
{
public static void main(String[] args) throws IOException
{
isDemo();
}
public static void isDemo() throws IOException
{
File f = new File("aaa.txt");
boolean b = f.exists();
System.out.println("b="+b);//false
if(!f.exists())
{
f.createNewFile();
}

//最好先判断是否存在
if(f.exists())
{
System.out.println(f.isFile());//true
System.out.println(f.isDirectory());//false
}

f = new File("aa\\bb");
f.mkdirs();
if(f.exists())
{
System.out.println(f.isFile());//false
System.out.println(f.isDirectory());//true
}

}
}

4、重命名:

renameTo(File):
File f1 = new File("c:\\a.txt");
File f2 = new File("c:\\b.txt");
f1.renameTo(f2);//将c盘的a.txt文件改名为b.txt文件

示例5:

import java.io.File;
import java.io.IOException;
public class FileMethodDemo
{
public static void main(String[] args) throws IOException
{
renameToDemo();
}
public static void renameToDemo() throws IOException
{
File f1 = new File("D:\\javaExc\\0.mp3");
File f2 = new File("D:\\javaExc\\123.mp3");
boolean b = f1.renameTo(f2);
System.out.println("b="+b);//true
}
}
示例6:(系统根目录和容量获取)
import java.io.File;import java.io.IOException;public class FileMethodDemo{public static void main(String[] args) throws IOException{listRootsDemo();}public static void listRootsDemo() throws IOException{File[] files = File.listRoots();for(File file : files){System.out.println(file);}File file = new File("d:\\");System.out.println("getFreeSpace:"+file.getFreeSpace());System.out.println("getTotalSpace:"+file.getTotalSpace());System.out.println("getUsableSpace:"+file.getUsableSpace());}}
Java基础---IO流(中)

示例7:(获取目录下的文件以及文件夹的名称)

import java.io.File;
import java.io.IOException;
public class FileMethodDemo
{
public static void main(String[] args) throws IOException
{
listDemo();
}
public static void listDemo() throws IOException
{
File file = new File("c:\\");
//获取目录下的文件以及文件夹的名称,包含隐藏文件
//调用list方法的File对象中封装的必须是目录,否则会产生NullPointerException
//如果访问的是系统级目录也会发生空指针异常
//如果目录存在但是没有内容,会返回一个数组,但长度为0
String[] names = file.list();
for(String name:names)
{
System.out.println(name);
}
}
}
Java基础---IO流(中)
示例8:(获取d盘javaExc目录下后缀名为java的文件)
import java.io.File;
import java.io.FilenameFilter;
public class FileMethodDemo
{
public static void main(String[] args)
{
listDemo();
}
public static void listDemo()
{
File file = new File("D:\\javaExc");
String[] names = file.list(new FilterByJava(".java"));
for(String name:names)
{
System.out.println(name);
}
}
}

class FilterByJava implements FilenameFilter
{
private String suffix;
public FilterByJava(String suffix)
{
this.suffix = suffix;
}
public boolean accept(File dir,String name)
{
return name.endsWith(suffix);
}
}

Java基础---IO流(中)
递归:
其实就是在使用一个功能过程中,又对该有需求。 就出现了函数自身调用。
注意:
1,一定要限条件,否则内存溢出。
2,使用递归时,调次数不要过多否则也会出现内存溢。
需求:
想要列出指定目录下的文件以及文件夹中的文件(子文件)
// 列出指定目录下的当前文件或者夹。// 想要列出当前目录下的文件夹中,其实就是在重新使用该功能。

import java.io.File;
class TestDemo
{
public static void main(String[] args)
{
File f = new File("C:\\myclass");
listDir(f,0);
}
public static void listDir(File dir,int level)
{
System.out.println(getLevel(level)+dir.getName());
level++;
File[] files = dir.listFiles();
for(int x = 0;x<files.length;x++)
{
if(files[x].isDirectory())//如果遍历到的是目录
listDir(files[x],level);//那么就行该功能的重复使用 递归。
else
System.out.println(getLevel(level)+files[x].getName());
}
}

public static String getLevel(int level)
{
StringBuilder sb = new StringBuilder();
sb.append("|--");
for(int x = 0;x<level;x++)
{
sb.insert(0,"| ");
}
return sb.toString();
}
}
Java基础---IO流(中)