概念
流是一组有序的数据序列,根据操作的类型,分为输入和输出(I/O),常与磁盘文件存取有关,源和地址可以是键盘、鼠标、内存或显示器窗口等
输入流
InputStream类是字节输入流的抽象类,是所有字节输入流的父类。该类中所有方法遇到的错误时会引发IOException异常。下面是对该类中一些方法的简要说明(并不是所有InputStream类的子类都支持以下方法)
read();从输入流中读取数据的下一个字节,没有可用字节时,返回-1
read(byte[] b);从输入流中读取一定长度的字节,并以整数的形式返回字节数
mark(int readlimit);在输入流的当前位置放置一个标记,readlimit参数告知此输入流在标记位置失效之前允许读取的字节数
reset();将输入指针返回到当前所做的标记处
skip(long n);跳过输入流上的n个字节并返回跳过的字节数
markSupported();如果当前流支持mark/reset操作就返回true
close();关闭此输入流并释放与该流关联的所有系统资源
Java中的字符都是Unicode编码,是双字节的。IputStream是用来处理字节的,并不适合处理字符文本。java为字符文本的输入专门提供了一套单独的类Reader。
Reader是字符输入流的抽象类,所有字符输入流的实现都是它的子类。
输出流
OutStream类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类。所有方法均返回void,遇到错误是引发IOException异常。
下面对其类中的方法做简单的介绍:
writer(int b);将指定的字节写入此输出流
writer(byte[] b);将b个字节从指定的byte数组写入此输出流
writer(byte[] b,int off,int len);将指定的byte数组中从偏移量off开始的len个字节写入此输出流
flush();彻底完成输出并清空缓存区
close();关闭输出流
Writer类是字符输出流的抽象类,所有的字符输出类的实现都是它的子类。
File类
java.io包中唯一代表磁盘文件本身的对象。File类定义了一些与平台无关的方法来操作文件马,可以通过调用File类中的方法,实现创建、删除、重命名文件等操作。主要用来获取文件本身的一些信息。
文件的创建与删除
创建文件对象的三种方法:
new File(String 全路径);
new File(String 父路径,String 子路径);如"D:/doc","le.txt"
new File(File 父路径对象,String 子路径);
当File创建一个对象时,如果目标文件不存在,可以调用createNewFile();方法创建,若想删除,可以调用delete();方法删除
import java.io.File;
import java.io.IOException;
public class file {
public static void main(String[] args) {
File file = new File("world.txt");
if (file.exists()){
file.delete();
System.out.println("文件已删除");
}else{
try {
file.createNewFile();
//file.mkdir();创建单个目录
//file.mkdirs();逐级创建文件,比如new File("D:/xx/world.txt")
System.out.println("文件已创建");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
file.mkdirs();的运行结果
获取文件信息
class fileOut{
public static void main(String[] args) {
File file = new File("world.txt");
if (file.exists()){//文件是否存在
String FileName = file.getName();//获取文件名
boolean ifRead = file.canRead();//文件是否可读
boolean ifWrite = file.canWrite();//文件是否可写
long length = file.length();//获取文件长度,单位:字节
String path = file.getAbsolutePath();//获取文件绝对路径
String parent = file.getParent();//获取父路径
boolean isFile = file.isFile();//判断文件是否存在
boolean isDirectory = file.isDirectory();//判断文件是否是一个目录(及文件夹)
boolean isHidden = file.isHidden();//文件是否有隐目录
long lastTime= file.lastModified();//获取文件最后修改时间,返回时间戳
System.out.println("文件名:"+FileName+"\n"+"可读:"+ifRead+"\n"+"可写:"+ifWrite+"\n"+"文件长度:"+length+"\n" +
"绝对路径:"+path+"\n"+"父路径:"+parent+"\n"+"是否存在:"+isFile+"\n" +
"是文件夹:"+isDirectory+"\n"+"隐藏目录:"+isHidden+"\n"+"最后修改时间:"+lastTime);
}else{
System.out.println("该文件不存在");
}
}
}
获取该路径下所有目录及子目录
private static void readFile(File f){
File[] files = f.listFiles();
for (File fi:files){
if (fi.isFile()){
//String name = fi.getName();获取文件名
//if (name.endsWith(".java"))如果文件以.java结尾,则输出文件
System.out.println("fi.getAbsolutePath() = " + fi.getAbsolutePath());
}else if (fi.isDirectory()){
readFile(fi);
}
}
}
文件输入输出流
FIleInputStream和FileOutputStream类
FIleInputStream和FileOutputStream类都是用来操作磁盘文件的如果用户对读取需求比较简单,则可以使用FileInputStream类,FileOutputStream类提供了基本的文件写入功能。
FileInputStream类常用的构造方法如下:
FileInputStream(String name);
FileInputStream(File file);
FileOutputStream与之相同,可以指定不存在的文件
下面演示两个实例:
import java.io.*;
import java.nio.charset.StandardCharsets;
public class fileInorOut {
public static void main(String[] args) {
File file = new File("world.txt");//创建文件对象
try {
FileOutputStream out = new FileOutputStream(file);//创建FileOutputStream对象
byte[] b = "我有一头小毛驴".getBytes(StandardCharsets.UTF_8);
out.write(b);//将数组内容写入文件
out.close();//关闭输出流
FileInputStream in = new FileInputStream(file);
byte[] read = new byte[1024];
int len = in.read(read);//读取文件内容
System.out.println("文件中的信息是:"+new String(read,0,len));
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
public class InputOutStreamDemo {
public static void main(String[] args) throws IOException {
/**
*在文件file3下有个1.txt文本,想把它上传到file3下的upload文件夹下
*/
//1.获取路径,如果不存在则创建
String srcDirectPath = "D:\\file3\\upload\\";
File file3 = new File(srcDirectPath);
if (!file3.exists()) file3.mkdirs();
//创建1.txt文件
File txt = new File("D:\\file3\\1.txt");
if (!txt.exists()) txt.createNewFile();
//2.创建OutputStream对象
OutputStream out = new FileOutputStream(txt);
//3.向文件中写入内容
StringBuilder sb = new StringBuilder();
while (sb.length()<1024){
sb.append("这是我写进去的东西");
}
byte[] bytes = sb.toString().getBytes(StandardCharsets.UTF_8);
out.write(bytes);
//5.创建InputStream对象
InputStream in = new FileInputStream(txt);
//根据指定的规则生成一个文本文档
OutputStream o = new FileOutputStream(srcDirectPath + UUID.randomUUID() + ".txt");
//创建字节数组,表示一次读取多少字节的内容
byte[] b = new byte[1024];
int len = 0;
//写入的大小超过1024时就需要用到循环,不然只写入前1024字节的内容
while ((len = in.read(b))!=-1){
o.write(b, 0, len);
}
//关闭流,最后使用的先关闭,最先使用的最后关闭
if (o!=null) o.close();
if (out!=null) out.close();
if (in!=null) in.close();
}
}
FileReader和FileWriter类
FIleInputStream和FileOutputStream类只提供了字节/字节数组的输入和输出,由于汉字占两个字节,如果使用字节流,读取不好可能会出现乱码现象,此时采用字符流更为合适。
下面是实例:(不知道JFrame的我的博客有写)
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
public class readerORwriter extends JFrame {
private JPanel jContentPane = null;//创建面板对象
private JTextArea jTextArea = null;//创建文本域
private JButton writerButton = null;
private JButton readButton = null;
private JPanel controltPanel = null;
private JButton getWriterButton(){
if (writerButton == null){
writerButton = new JButton("写入文件");
writerButton.addActionListener(new ActionListener() {//给按钮添加监听事件
@Override
public void actionPerformed(ActionEvent e) {
try {
File file = new File("test.txt");//创建文件对象
file.createNewFile();//创建文件
FileWriter writer = new FileWriter(file);//创建FileWriter对象
writer.write(jTextArea.getText());//获取文本域中的文本并写入磁盘
writer.close();//关闭流
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
});
}
return writerButton;
}
private JButton getReadButton(){
if (readButton == null){
readButton = new JButton("读取文件");
readButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
File file = new File("test.txt");
try {
FileReader read = new FileReader(file);
char[] text = new char[1024];
int len = read.read(text);//读取文件长度
jTextArea.append("\n文件内容如下:\n"+new String(text,0,len));
read.close();
} catch (FileNotFoundException fileNotFoundException) {
fileNotFoundException.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
});
}
return readButton;
}
public readerORwriter(){
super();
initialize();
}
private void initialize(){
// this.setVisible(true);
this.setSize(300,200);
// this.setDefaultCloseOperation(3);
this.setTitle("测试写入读取");
this.setContentPane(getjContentPane());
}
private JPanel getjContentPane(){
if (jContentPane == null){
jContentPane = new JPanel();
jContentPane.setLayout(new BorderLayout());
jContentPane.add(getJTextArea(),BorderLayout.NORTH);
jContentPane.add(getControlPanel(),BorderLayout.SOUTH);
}
return jContentPane;
}
private JPanel getControlPanel() {
if (controltPanel == null){
controltPanel = new JPanel();
controltPanel.add(getWriterButton());
controltPanel.add(getReadButton());
}
return controltPanel;
}
public JTextArea getJTextArea() {
if (jTextArea == null) {
jTextArea = new JTextArea(7,15);
jTextArea.setLineWrap(true);
}
return jTextArea;
}
public static void main(String[] args) {
readerORwriter r = new readerORwriter();
r.setVisible(true);
r.setDefaultCloseOperation(3);
}
}
带缓存的输入输出流
缓存是I/O的一种性能优化,缓存流为I/O流增加了内存缓存区。有了缓存区使得在流上执行skip()、mark()、reset()方法都成为可能
BufferedInputStream与BufferedOutputStream类
BufferedInputStream类可以对所有InputStream类进行缓存区的包装以达到性能的优化。它的两个构造方法:
BufferedInputStream(InputStream in);//创建一个带有32个字节的缓存流
BufferedInputStream(InputStream in,int size);//按指定大小创建缓存区
BufferedOutputStream输出信息和用OutputStream完全一样,只不过BufferedOutputStream有一个flush()方法用来将缓存区的数据强制输出完。它的两个构造方法:
BufferedOutputStream(OutputStream out);
BufferedOutputStream(OutputStream out,int size);
private static void testFile3(String src) throws IOException {
// 1.通过file将源文件路径建立联系,读取文件的路径信息
File srcFile = new File(src);
// 2.创建上传后的路径,不存在的话进行创建
String path= "D:\\upload\\";
File uploadFile = new File(path);
if(!uploadFile.exists()) {//判断是否存在该文件
uploadFile.mkdir();//一层文件夹的创建,如果是多层文件都不存在,需要用到mkdirs方法进行创建
}
if(srcFile.exists()) {
//创建输入缓冲流 ,也叫包装流
InputStream is = new BufferedInputStream(new FileInputStream(srcFile));
String distPath = path + UUID.randomUUID()+srcFile.getName();
OutputStream os = new BufferedOutputStream(new FileOutputStream(distPath));
//读和写的具体实现
byte[] buf = new byte[1024];//通过字节数组提高读取效率
int len =0;//每次读取的长度,如果读取到文件末尾,该值==-1,代表结束
while ((len=is.read(buf))!=-1) {
os.write(buf, 0, len);
}
os.close();
is.close();
}
}
BufferedReader与BufferedWrtier类
BufferedReader与BufferedWrtier类是以行为单位进行输入/输出
BufferedReader类的常用方法:
read();//读取单个字符
readLine();//读取一个文本行,并将其返回为字符串,若无数据可读,则返回null
BufferedWrtier类的常用方法:
wirte(String s,int off,int len);//写入字符串的某一部分
flush();//刷新该流的缓存
newLine();//写入一个行分隔符
注意:在使用BufferedWrtier类的wirte()方法时,数据并没有立刻被写入至输出流,而是先进入缓存区中,如果想立刻将缓存区中的数据写入输出流,一定要调用flush()方法。
import java.io.*;
public class buffer {
public static void main(String[] args) {
//定义字符串数组
String[] text = {
"好久不见",
"最近好吗",
"常联系"
};
File file = new File("word.txt");
try {
FileWriter fileWriter = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fileWriter);//BufferedWriter需要传一个writer对象为参数
for (int i = 0; i < text.length; i++) {//遍历数组写入磁盘文件
bw.write(text[i]);
bw.newLine();
}
bw.close();
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
FileReader fileReader = new FileReader(file);
BufferedReader br = new BufferedReader(fileReader);
String s = null;//创建字符串接收数据
int i = 0;
//创建循环,如果文本行不为空,则进入循环
while ((s = br.readLine())!=null){
i++;
System.out.println("第"+i+"行:"+s);
}
br.close();
fileReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedReader同样需要一个reader对象作为参数。流关闭是一个良好的写代码习惯,防止占用资源,一定不要忘记哦。
数据输入输出流
DataInputStream类与DataOutputStream类允许应用程序以与机器无关的方式从底层输入流中读取基本java数据。也就是说,当读取一个数据时,不必再关心这个数值应当是哪个字节。构造方法如下;
DataInputStream(InputStream in);//使用指定的基础InputStream创建一个DataInputStream
DataOutStream(OutputStream out);//创建一个新的字节输出流,将数据写入指定基础输出流。
DataOutStream提供如下三种写入字符串的方法:
writeBytes(String s);
writeChars(String s);
writeUTF(String s);
DataInputStream只有一个readUTF()方法用于在一个连续的字节流读取一个字符串,如果没有特殊的标记作为一个字符串的结尾,并且不知道这个字符串的长度,就无法知道读取到什么位置才是这个字符串的结束。DataOutStream类中只有writeUTF()方法向目标设备中写入字符串的长度,所以也能准确地读回写入的字符串。
import java.io.*;
public class data {
public static void main(String[] args) {
try {
FileOutputStream fo = new FileOutputStream("word.txt");//创建文件输出流对象
DataOutputStream da = new DataOutputStream(fo);//创建数据输出流对象
da.writeUTF("UTF输入");
da.writeChars("Char输入");
da.writeBytes("Byte输入");
da.close();
FileInputStream in = new FileInputStream("word.txt");
DataInputStream di = new DataInputStream(in);
System.out.println(di.readUTF());//输出文件信息
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
只输出由UTF格式写入的数据
zip压缩输入输出流
ZIP压缩管理文件是一种十分典型的文件压缩形式,使用它可以节省存储空间。
压缩文件
ZipOutputStream(OutputStream out);//将文件压缩为zip文件。
ZipOutputStream类的常用方法如下:
putNextEntry(ZipEntry e);//开始写一个新的ZipEntry(代表一个压缩文件的进入点),并将流内的位置移至此entry(进入点)所指的数据的开头。
write(byte[] b,int off,int len);//将字节数组写入当前zip条目数据。
finish();//完成写入zip输出流的内容,无需关闭它所配合的OutputStream
setComment(String comment);//可设置此zip文件的注释文字
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class zipTest {
private void zip(String zipFileName, File inputFile){
try {
ZipOutputStream out = new JarOutputStream(new FileOutputStream(zipFileName));//创建zip输出流对象
zip(out, inputFile, "");//调用方法
System.out.println("压缩中...");
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void zip(ZipOutputStream out, File f,String base){//重载方法
if (f.isDirectory()){//判断是否是一个目录
File[] fl = f.listFiles();//获取文件路径数组
System.out.println("路径数组:"+ Arrays.toString(fl));
try {
out.putNextEntry(new ZipEntry(base+"/"));//写入此目录的进入点
base = base.length()==0?"":base+"/";//判断参数是否为空
for (int i = 0; i < fl.length; i++) {//遍历数组中的文件
zip(out, fl[i],base+fl[i]);
}
} catch (Exception e) {
e.printStackTrace();
}
}else{
try {
out.putNextEntry(new ZipEntry(base.substring(3)));
FileInputStream in = new FileInputStream(f);
System.out.println(base.substring(3));//去掉根目录--》D:/
int b;
while ((b = in.read())!=-1){//如果没有到达流的尾部
out.write(b);//将字节写入当前zip条目
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
zipTest zt = new zipTest();
zt.zip("D:/zip测试.zip", new File("D:/zip测试"));//参数为压缩后的路径/文件名和要压缩的文件/目录路径
System.out.println("压缩完成");
}
}
解压缩zip文件
ZipInputStream类可读取ZIP压格式的文件,包括已压缩和未压缩的条目。构造方法:ZipInputStream(InputStream in);常用方法如下:
read(byte[] b,int off,int len)//读取目标b数组内off偏移量的单位,长度是len的字符
available()//判断是否已读完目前entry所指的数据。已读完返回0,反之返回1
closeEntry()//关闭当前ZIP条目并定位流以读取下一个条目
skip(long n)跳过当前ZIP条目中指定的字节数
getNextEntry()//读取下一个ZipEntry,并将流内的位置移至该entry所指数据的开头
createZipEntry(String name)//以指定的name参数新建一个ZipEntry对象
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.jar.JarInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class gZip {
public static void main(String[] args) {
try {
ZipInputStream zin = new JarInputStream(new FileInputStream("D:\\zip测试.zip"));//指明要解压的文件
ZipEntry zpe = zin.getNextEntry();//获取下一个ZipEntry
while (((zpe = zin.getNextEntry()) != null) && !zpe.isDirectory()) {//如果entry不为空且不在同一目录下
File file = new File("D:\\"+zpe.getName().substring(0, 5));//获取文件夹目录
File file2 = new File("D:\\"+zpe.getName());//获取文件目录
System.out.println(file);
if (!file.exists()) {//如果文件不存在
file.mkdirs();//创建文件所在文件夹
}
file2.createNewFile();//创建文件
zin.closeEntry();
System.out.println(zpe.getName() + "解压成功");
}
zin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
打印流
因为用法和前面的一样,功能也一样,那我们就直接上代码吧
先看看创建对象时的参数列表吧
然后是使用写入的参数列表
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class printIO {
public static void main(String[] args) {
PrintWriter printWriter = null;
try {
//创建一个打印流对象,传入一个文件对象
printWriter = new PrintWriter(new File("D:\\catch\\ideas\\IO\\text"));
printWriter.write("ass");
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}finally {
printWriter.close();
}
}
}
还有一个PrintStream和PrintWriter的区别就是前者有自动缓冲的参数,后者没有
小结
基本的java输入输出流到这结束!