输入输出流(每日笔记)
本人初识java,如有错误或者不足,虚心求各位大神教导
此总结只限老师提到的知识点,当然还有其它的知识点, java的水不浅,需要慢慢的摸索
什么是输入流?什么是输出流?
输入流
简单的说 输入流 就是把文件读到内存。
输出流
输出流 就是把内存中存储流的生成文件。
例如:修改一图片 需要通过输入流把图片读到内存,相应的软件对图片进行处理。处理完以后。修改好的“图片”仅仅是在内存中。需要用输出流进行保存。生成新修改的图片。
- java中什么是文件
- 相关记录或放在一起的数据集合,文件夹和文件都属于文件
- 文件储存在哪里
- 磁盘
- java程序如何访问文件属性?
- JAVA IPI:java.io.File
File类
包:java.io
File对象的创建
File file = new File("d:\\HelloWorld.java")
File常用方法
-
mkdir():创建单层文件夹
public boolean mkdir()
-
mkdir():创建多层文件夹
public boolean mkdirs()
-
getName():获取文件名
public String getName()
-
getAbsolutePath():获取指定文件的绝对路径
public String getAbsolutePath()
-
getPath():获取指定文件的相对路径
public String getPath()
-
delete():删除指定的文件
public boolean delete()
-
createNewFile()创建一个新的文件
public boolean createNewFile() throws IOException
-
list():获取指定file对象下的文件文件名存入String[]中
public String[] list(FilenameFilter filter)
-
listFile():获取指定file对象下的file对象
public File[] listFiles() //此方法重写toString方法
-
等等一系列方法
示例:
查询指定路径文件夹内所有包含"1.txt"的文件路径,并记录总条数
public class FileTest {
private static Integer count = 0;
public static Integer getFilesPath(String fileName, String dirName) {
File file = new File(dirName);
//获取指定文件夹下所有文件并将指定文件夹下所有的文件遍历
File[] files = file.listFiles();
for (File file1 : files) {
//判断是否是文件,如果是文件就输出路径,如果不是文件就继续遍历
if (file1.isFile()) {
if (file1.getName().equals(fileName)) {
System.out.println(file1.getAbsolutePath());
count++;
}
} else {
//递归
getFilesPath(fileName, file1.getAbsolutePath());
}
}
return count;
}
public static void main(String[] args) {
String fileName = "1.txt";
String dirName = "E:\\upload";
Integer files = FileTest01.getFilesPath(fileName, dirName);
System.out.println(fileName+"文件在"+dirName+"中出现了" + files + "次");
}
}
我们了解了File类,发现File类可以操作查看文件,但是怎么操作文件内容呢?
IO流
我们知道一个字节有8位(bit),那么一个文件在计算机中传输,是先将文件拆分成最小的单位然后进行传输,再重新拼装形成一个文件,就像一股水流一样,bit就相当于水分子,字节相当于水滴
分类
- 字节流:是以8位的byte字节作为传输单元
- 输入流:外部数据写入程序 以InputStream 为基类
- 输出流:程序内部数据写入外部 以OutputStream为基类
- 字符流:是以16位的Unicode码作为传输单元
- 输入流:Reader为基类
- 输出流:Writer为基类
字节流
FileInputStream
-
包:java.io
-
常用方法
-
read(byte byte):
- 每次调用读取一个字节
- 当从输入流中读取出数据,返回的是读取字节的字节数,当从输入流中没有读取字节数时则返回-1
public int read(byte b[], int off, int len) throws IOException //b[]为缓冲区 off为开始索引 len为缓冲区大小
-
close()
public void close() throws IOException
-
等等方法
-
-
示例:
public static void main(String[] args) { //创建流对象 InputStream fileInputStream = null; try { fileInputStream = new FileInputStream("E:\\upload\\1.txt"); //读取数据 int read = fileInputStream.read(); //将数据输出 byte[] bytes = {(byte)read}; System.out.println(new String(bytes)); //这里直接catch一个大的Exception } catch (Exception e) { e.printStackTrace(); }finally { //关闭资源 if (fileInputStream!=null){ try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
注意这里读取流的方式是一位一位读取的,如果文件庞大十分影响效率,所以这里我们引出了个思想:
缓冲区 -
缓冲区的作用:
- 缓冲区就是存在于内存中的一个数组。对于输出流,输出的数据会先进入缓冲区,缓冲区满再自动刷新到硬盘的文件中,因为减少了内存和硬盘之间的读写次数,所以提高了效率。
-
示例:将指定文件输出到控制台
public class FileInputStreamTest01 { public static void main(String[] args) { FileInputStream fis = null; try { //创建流对象 fis = new FileInputStream("E:\\upload\\a.txt"); //缓冲区 byte[] bytes = new byte[1024]; int len; while ((len=fis.read(bytes))!=-1){ //将内容流入缓冲区,并输出 fis.read(bytes,0,len); System.out.println(new String(bytes)); } } catch (Exception e) { e.printStackTrace(); }finally { //关闭资源 try { if (fis!=null){ fis.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
注意使用完流对象,需要关闭流对象
FileOutputStream
包:java.io
了解过了FileInputStream输入流与缓冲区之后,输出流FileOutputStream与之相同
常用方法:
void write(byte[] b)
void write(byte[] b, int off, int len)
void write(int b)
void close()
同样的OutputStream也有缓冲区
案例:复制文件
public class OutputStreamTest {
public static void main(String[] args) {
InputStream is = null;
OutputStream os = null;
try {
//开启输入输出流
is = new FileInputStream("E:/upload/img.png");
os = new FileOutputStream("E:/upload/img/img.png");
//缓冲区
byte[] bytes = new byte[1024];
int len = 0;
while ((len = is.read()) != -1) {
//将流中数据写入目的地
os.write(bytes, 0, len);
}
//这里直接catch一个Excpetion(为了省事)
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭资源
try {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符流
字符流:是以16位的Unicode码作为传输单元
Reader:
字符输入流的基类
常用子类:
BufferedReader
FilterReader
InputStreamReader
常用方法:
read()
close()
Writer
字符输入流的基类
常用子类:
BufferedWriter
FilterWriter
OutputStreamWriter
常用方法:
read()
close()
Reader与Writer的用法与字符流类似,也有缓冲区的思想,不同的是字节流的缓冲区是一个byte[]数组,字符流的缓冲区是一个char[]数组,如果流中内容有中文字符需要注意编码问题:
Reader的子类中有一个类:InputStreamReader我们看这个类的构造方法
InputStreamReader(InputStream in)
InputStreamReader(InputStream in, Charset cs)
InputStreamReader(InputStream in, CharsetDecoder dec)
InputStreamReader(InputStream in, String charsetName)
我们可以使用
InputStreamReader(InputStream in, String charsetName)
Writer的子类OutputStreamWriter与上面类似,都可以指定字符集
这里我为了书写方便异常我就直接throws了,大家不要学我
public static void main(String[] args) throws IOException {
InputStream is = new FileInputStream("E:\\upload\\a.txt");
InputStreamReader isr = new InputStreamReader(is, "utf-8");
OutputStream os = new FileOutputStream("E:\\upload\\file\\a.txt");
OutputStreamWriter osw = new OutputStreamWriter(os, "utf-8");
char[] chars = new char[1024];
int len;
while ((len = isr.read(chars)) != -1) {
osw.write(chars, 0, len);
osw.flush();
}
isr.close();
is.close();
osw.close();
os.close();
}
这里注意:编码问题遇到的问题有很多, 这里不做细讲
BufferedReader与BufferedWriter
为了提高字符流读写的效率,引入了缓冲机制,进行字符批量的读写,提高了单个字符读写的效率。BufferedReader用于加快读取字符的速度,BufferedWriter用于加快写入的速度
ReadLine()方法就是Read()方法的功能进行增强 可以读一行文字。
案例:
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("E:\\upload\\a.txt");
BufferedReader br = new BufferedReader(reader);
FileWriter writer = new FileWriter("E:\\upload\\file\\a.txt");
BufferedWriter bw = new BufferedWriter(writer);
String str;
while ((str = br.readLine()) != null) {
bw.write(str);
bw.newLine();
}
bw.close();
writer.close();
reader.close();
br.close();
}
IO流使用规律总结:
- 明确要操作的数据是数据源还是数据目的(要读还是要写)
- 源文件:InputStream Reader
- 目的文件:OutputStream Writer
- 明确要操作的设备上的数据是字节还是文本
- 源:
- 字节:InputStream
- 文本:Reader
- 目的:
- 字节:OutputStream
- 文本:Writer
- 源:
- 明确是否需要额外功能?
- 需要转换——转换流 InputStreamReader OutputStreamWriter
- 需要高效——缓冲流Bufferedxxx