一、流
1、概述
(1)、简介
流是个抽象的概念,是对输入输出设备的抽象。流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序为参考,如果数据的流向是程序至设备,我们成为输出流,反之我们称为输入流。
(2)、分类
-
按流向分:
输入流: 程序可以从中读取数据的流。
输出流: 程序能向其中写入数据的流。
-
按数据传输单位分:
字节流: 以字节为单位传输数据的流
字符流: 以字符为单位传输数据的流
-
按功能分:
节点流: 用于直接操作目标设备的流
过滤流: 是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。
(3)、结构
Java所有的流类位于java.io包中,都分别继承字以下四种抽象流类型。
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
(4)、常用流类
a、输入流和输出流
输入流:InputStream或者Reader:从文件中读到程序中;输出流:OutputStream或者Writer:从程序中输出到文件中。
输入字节流 InputStream
-
InputStream 是所有的输入字节流的父类,它是一个抽象类。
-
ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。
-
PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。
-
ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。
b、输出字节流 OutputStream
-
OutputStream 是所有的输出字节流的父类,它是一个抽象类。
-
ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。
-
PipedOutputStream 是向与其它线程共用的管道中写入数据。
-
ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。
b、节点流
节点流:直接与数据源相连,读入或读出。 直接使用节点流,读写不方便,为了更快的读写文件,才有了处理流。
常用的节点流
-
父 类 :InputStream 、OutputStream、 Reader、 Writer
-
文 件 :FileInputStream 、 FileOutputStrean 、FileReader 、FileWriter 文件进行处理的节点流
-
数 组 :ByteArrayInputStream、 ByteArrayOutputStream、 CharArrayReader 、CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
-
字符串 :StringReader、 StringWriter 对字符串进行处理的节点流
-
管 道 :PipedInputStream 、PipedOutputStream 、PipedReader 、PipedWriter 对管道进行处理的节点流
c、处理流
处理流和节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。
常用的处理流
-
缓冲流:BufferedInputStrean 、BufferedOutputStream、 BufferedReader、 BufferedWriter 增加缓冲功能,避免频繁读写硬盘。
-
转换流:InputStreamReader 、OutputStreamReader实现字节流和字符流之间的转换。
-
数据流: DataInputStream 、DataOutputStream 等-提供将基础数据类型写入到文件中,或者读取出来。
d、转换流
InputStreamReader 、OutputStreamWriter 要InputStream或OutputStream作为参数,实现从字节流到字符流的转换。
(5)、字节流和字符流的区别
-
读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
-
处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
-
字节流:一次读入或读出是8位二进制。
-
字符流:一次读入或读出是16位二进制。
2、文件类
File类是I/O包中唯一代表磁盘文件本身的对象,File类定义了一些与平台无关的方法来操作文件,通过调用File类提供的各种方法,能够完成文件的创建,删除,重命名,判断文件的读写权限及文件是否存在,设置和查询文件的最近修改时间等操作
文件类的常用方法
-
创建文件对象:File file=new File(“文件路径”);
-
exists方法:判断文件是否存在
-
canWrite方法:判断文件是否可写
-
getName方法:获取文件的名称
-
length方法:获取文件大小
-
createNewFile方法:创建文件
-
delete方法:删除文件(注意:一旦删除,无法在垃圾箱中找回)
-
isDirectory方法:判断文件是否是目录
生成File对象
File(String directoryPath)
-
directoryPath是文件的路径名
File方法的使用
import java.io.File;
class File_Test {
public static void main(String[] args) {
File f = new File("C:\\Users\\Admin\\Documents\\Eclipse-workspace\\File\\.project");
if(f.exists())
f.delete();
else
try {
f.createNewFile();
}catch(Exception e) {
System.out.println(e.getMessage());
}
//getName(),返回文件名
System.out.println("文件名:"+ f.getName());
//getPath(),返回文件路径
System.out.println("文件路径:"+f.getPath());
//getAbsolutePath(),返回绝对路径
System.out.println("绝对路径:"+f.getAbsolutePath());
//getParent(),返回父文件夹名
System.out.println("父文件名:"+f.getParent());
//exists(),判断文件是否存在
System.out.println(f.exists()?"文件存在":"文件不存在");
//canWrite(),判断文件是否可写
System.out.println(f.canWrite()?"文件可写":"文件不可写");
//canReade(),判断文件是否可读
System.out.println(f.canRead()?"文件可读":"文件不可读");
//isDirectory(),判断是否是目录
System.out.println(f.isDirectory()?"是":"不是"+"目录");
//isFile(),判断是否是文件
System.out.println(f.isFile()?"是文件":"不是文件");
//isAbsoulte(),是否是绝对路径
System.out.println(f.isAbsolute()?"是绝对路径":"不是绝对路径");
//lastModified(),返回文件最后修改时间
System.out.println("文件最后修改时间:"+f.lastModified());
//length(),文件的长度
System.out.println("文件大小:"+f.length()+"Byte");
}
}
输出:
文件名:.project
文件路径:C:\Users\Admin\Documents\Eclipse-workspace\File\.project
绝对路径:C:\Users\Admin\Documents\Eclipse-workspace\File\.project
父文件名:C:\Users\Admin\Documents\Eclipse-workspace\File
文件不存在
文件不可写
文件不可读
不是目录
不是文件
是绝对路径
文件最后修改时间:0
文件大小:0Byte
读取给定文件的相关属性,如果该文件不存在则创建该文件
import java.io.File;
import java.util.Scanner;
class File_Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入文件名:");
String s = sc.nextLine();
File f = new File(s);
System.out.println("文件名: "+f.getName());
System.out.println("文件大小为: "+f.length()+" Byte");
System.out.println("文件所在路径为: "+f.getAbsolutePath());
if(f.isHidden())
System.out.println("该文件是一个隐藏文件");
else {
System.out.println("该文件不是一个隐藏文件");
}
if(!f.exists()) {
System.out.println("该文件不存在");
try {
f.createNewFile();
System.out.println("文件创建成功");
}catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
}
输出1:
请输入文件名:
C:\Users\Admin\Documents\Eclipse-workspace\File\.project
文件名: .project
文件大小为: 380 Byte
文件所在路径为: C:\Users\Admin\Documents\Eclipse-workspace\File\.project
该文件不是一个隐藏文件
输出2:
请输入文件名:
C:\Users\Admin\Documents\Eclipse-workspace\File\null
文件名: null
文件大小为: 0 Byte
文件所在路径为: C:\Users\Admin\Documents\Eclipse-workspace\File\null
该文件不是一个隐藏文件
该文件不存在
文件创建成功
遍历目录文件
遍历目录文件的方法
boolean | mkdir() | 创建一个目录,并返回创建结果,成功返回true,否则返回false |
boolean | mkdirs() | 创建一个包括父目录在内的目录,创建所有目录成功返回true,否则返回false |
String[] | list() | 获取目录下字符串表示形式的文件名和目录名 |
String[] | list(FilenameFilter filter) | 获得满足指定过滤器条件的媳妇传表示形式的文件名和目录名 |
File[] | listFiles() | 获取目录下文件表示形式的文件名和目录名 |
File[] | listFiles(FileFilter filter) | 获取满足指定过滤器文件条件的文集那表示形式的文件名和目录名 |
FIle[] | listFiles(FilenameFilter filter) | 获取满足指定过滤器路径和文件条件的文件表示形式的文件名和目录名 |
列出给定目录下所有的文件名,并列出给定扩展名的所有文件名
import java.io.File;
import java.io.FilenameFilter;
import java.util.Scanner;
class File_Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要访问的目录:");
String s = scanner.nextLine(); //读取访问的目录
File dirFile = new File(s); //创建目录文件对象
String[] allresults = dirFile.list(); //获取目录下所有文件名
for(String name:allresults) {
System.out.println(name); //输出所有文件名
}
System.out.println("输入扩展文件名:");
s = scanner.nextLine();
Filter_Name fileAccept = new Filter_Name(); //创建文件名过滤对象
fileAccept.setExtendName(s); //设置过滤条件
String result[] = dirFile.list(fileAccept); //获取满足条件的文件名
for(String name:result) {
System.out.println(name); //输出满足条件的文件名
}
}
class Filter_Name implements FilenameFilter
{
String extendName;
public void setExtendName(String s) {
extendName = s;
}
public boolean accept(File dir,String name) { //重写接口中的方法,设置过滤内容
return name.endsWith(extendName);
}
}
}
删除文件和目录
使用File类的delete()方法即可删除,但delete方法在使用时,必须保证目录下是空的,否则可以使用递归的方法删除。
import java.io.File;
import java.io.IOException;
public class DeleteFile{
public static void deleteFile(File file) {
File[] fileArray = file.listFiles();
if(fileArray.length>0) {
for(int i = 0 ;i < fileArray.length;i++) {
if(fileArray[i].isFile()) {
if(fileArray[i].delete()) {
System.out.println("删除成功");
}else {
System.out.println("删除不成功");
}
}else {
deleteFile(fileArray[i]);
}
}
}
if(file.delete()) {
System.out.println("删除成功");
}else {
System.out.println("删除不成功");
}
}
public static void main(String[] args) throws IOException{
File file = new File("D:\\Program Files");
deleteFile(file);
}
}
输出:
删除成功
删除成功
删除成功
3、字节流
字节流是以字节为单位来处理数据的,由于字节流不会对数据进行任何转换,因此可以用来处理二进制形式的数据,
(1)、字节输入流
字节输入流的作用是从数据输入源获取字节数据到应用程序中
int available() | 返回当前可读的输入字节数 |
void close() | 关闭输入流,关闭之后若再读取会产生IOExceptuon异常 |
void mark(int numBytes) | 在输入流的当前点放置一个标记,该流在读取numBytes这个字节时都保持有效 |
boolean markSupported() | 如果调用的流支持mark()/reset()就返回true |
int read | 如果下一字节刻度就返回一个整型,遇到文件尾时返回-1 |
int read(byte buffer[]) | 试图读取buffer.length个字节到buffer中,并返回实际成功读取的字节数。遇到文件尾时返回-1 |
int read(byte buffer[],int offset,int numBytes) | 试图读取buffer中从buffer[offset]开始的numBytes个字节,返回实际读取的字节数,遇到文件结尾时范围-1 |
void reset() | 重新设置输入指针到先前设置的标志处 |
long skip(long numBytes) | 忽略numBytes个输入字节,返回实际忽略的字节数 |
FileInputStream类创建一个能从文件读取字节的InputStream类,两个常用构造方法如下:
FileInputStream(String filepath)
InputStream f = new FileInputStream("D:\FileInputStream");
FileInputStream(File fileObj)
File f = new File("D:\FileInputStream");
InputStream f1 = new FileInputStream(f);
第一个构造方法更常用,第二个则允许在把文件赋给输入流之前用File方法更进一步检查文件。当一个FileInputStream被创建时,它可以被公开读取。
从磁盘文件中读取指定文件并显示出来
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
public class InputStream{
public static void main(String[] args) {
byte[] b = new byte[1024]; //设置字节缓冲区
int n = -1;
System.out.println("请输入要读取的文件名:");
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();//获得要读取的文件名
try {
FileInputStream in = new FileInputStream(str); //创建字节输入流
while((n=in.read(b, 0, 1024))!=-1) {
String s = new String(b,0,n);
System.out.println(s);
}
in.close();
}
catch(IOException e) {
System.out.println("文件读取失败");
}
}
}
输出:
请输入要读取的文件名:
D:\FileInputStream\FileInputStream.txt
Hello,InputStream
(2)、字节输出流
字节输出流的作用是将字节数据从应用程序(内存)中传送到输出目标
void close() | 关闭输入流,关闭后的写操作会产生IOException异常 |
void flush() | 刷新输出缓冲区 |
void write(int b) | 向输出流写入单个字节 |
void write(byte buffer[]) | 向一个输出流 |
void write(byte buffer[],int offset,int numBytes) | 写数组buffer以buffer[offset]为起点的numBytes个字节区域内的内容 |
FileOutputStream创建了一个可以向文件写入字节的类OutputStream,构造方法如下:
FileOutputStream(String filePath)
FileOutputStream(File fileObj)
FileOutputStream(String filePath,boolean append)
向一个磁盘文件中写入数据,第二次写操作采用追加方式完成
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class OutputStream{
public static void main(String[] args) {
// TODO Auto-generated method stub
String content; //代输出字符串
byte[] b; //输出字节流
FileOutputStream out; //文件输出流
Scanner scanner = new Scanner(System.in);
System.out.println("请输入文件名:");
String filename = scanner.nextLine();
File file = new File(filename); //创建文件对象
if(!file.exists()) { //判断文件是否存在
System.out.println("文件不存在,是否创建?(y/n)");
String f = scanner.nextLine();
if(f.equalsIgnoreCase("n"))
System.exit(0); //不创建,退出
else
{
try {
file.createNewFile(); //创建新文件
}
catch(IOException e) {
System.out.println("创建失败");
System.exit(0);
}
}
}
try { //向文件中写内容
content = "abc";
b = content.getBytes();
out = new FileOutputStream(file);
out.write(b);
out.close();
System.out.println("文件写操作成功!");
}
catch(IOException e) {
e.getMessage();
}
try { //向文件中追加内容
System.out.println("请输入追加的内容:");
content = scanner.nextLine();
b=content.getBytes();
out = new FileOutputStream(file,true); //创建可追加内容的输出流
out.write(b); //完成追加写操作
out.close(); //关闭输入流
System.out.println("文件追加写操作成功!");
scanner.close();
}catch(IOException e) {
e.getMessage();
}
}
}
输出:
请输入文件名:
D:\FileInputStream\FileInputStream.txt
文件写操作成功!
请输
4、字符流
(1)、字符输入流
Reader是专门用于输入数据的字符操作流,它是一个抽象类,定义如下:
public abstract class Reader
extends Object
implements Readable,Closeable
Reader类的所有方法
abstract void close() | 关闭输入源 |
void mark(int numChars) | 在输入流的当前位置设立一个标志,该输入流在numChars个字符被读取之前有效 |
boolean markSupported() | 判断该流是否支持mark()/resert(),是则返回true |
int read() | 如果调用的输入流的下一个字符可读则返回一个整型。遇到文件尾时返回-1 |
int read(char buffer[]) | 试图读取buffer中的buffer.length个字符,返回实际成功读取的字节数。遇到文件尾时返回-1 |
abstract int read(char buffer[],int offset,int numChars) | 试图读取buffer中的buffer[offset]开始的numChars个字符,返回实际成功读取的字节数。遇到文件尾时返回-1 |
boolean ready() | 如果下一个输入请求不等待则返回true,否则返回false |
long skip(long numChars) | 跳过numChars个输入字符,返回跳过的字符。设置输入指针到先前设立的标志处 |
(2)、字符输出流
Writer是定义流式字符输出的抽象类,所有该类的方法都返回一个void值并在出错的条件下引发IOException异常
Writer方法:
abstract void close() | 关闭输出流 |
abstract void flush() | 定制输出状态以使每个缓冲器都被清除 |
void write(int ch) | 向输入流写入单个字符 |
void write(char buffer[]) | 向一个输出流写一个完整的字符数组 |
abstract void write(char buffer[],int offset,int numChars) | 向调用的输出流写入数组buffer以buffer[offset]为起点,长度为numChars个字符的区域内的内容 |
void write(String str) | 向调用的输出流写str |
void write(String str,int offset,int numChars) | 写数组str中以offset为起点,长度为numChars个字符的区域内的内容 |
向BufferedReader类和BufferedWriter类读写文件
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Buffer_Test{
public static void main(String[] args) throws IOException {
String strLine;
String strTest = "Welcome to the Java World!";
BufferedWriter bwFile = new BufferedWriter(new FileWriter("demo.txt"));
bwFile.write(strTest,0,strTest.length());
bwFile.flush();
System.out.println("成功写入demo.txt!\n");
BufferedReader bwReader = new BufferedReader(new FileReader("demo.txt"));
strLine = bwReader.readLine();
System.out.println("从demo.txt读取的内容为:");
System.out.println(strLine);
}
}
输出:
成功写入demo.txt!
从demo.txt读取的内容为:
Welcome to the Java World!
5、文件流
FileReader类
FileReader类创建了一个可以读取文件内容的Reader类,常用构造方法如下,他们都能引发一个FileNotFoundException异常
FileReader(String filePth)
FileReader(String fileObj)
- filePath是一个文件的完整路径
- fileObj是描述该文件的File对象
FileWrite类
FileWrite类创建了一个可以写文件的write类,常用构造方法如下,引发IOExcetion或SecurityException异常
FileWrite(String filePath)
FileWrite(String filePath,boolean append)
FileWrite(File fileObj)
-
filePath是文件的绝对路径
-
fileObj是描述该文件的File对象
用文件流实现文件的复制功能
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Scanner;
public class FileTest{
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入源文件名和目的文件名:");
String s = scanner.next(); //读取源文件名
String d = scanner.next(); //读取目的文件名
File f1 = new File(s); //创建源文件对象
File f2 = new File(d); //创建目的文件对象
if(!f1.exists()) {
System.out.println("被复制文件不存在");
System.exit(1);
}
InputStream input = new FileInputStream(f1); //创建源文件流
OutputStream output = new FileOutputStream(f2);
if((input!=null)&&(output!=null)) {
int temp = 0;
while((temp=input.read())!=(-1))
output.write(temp);
}
input.close();
output.close();
System.out.println("文件复制成功!");
}
}
输出:
请输入源文件名和目的文件名:
D:\FileInputStream\demo.txt
D:\FileInputStream\test.txt
文件复制成功!
6、字符缓冲流
(1)、字节缓冲IO流
先通过实体输入流(FileInputStream)对象逐一读取字节数据并存入缓冲区,应用程序则从缓冲区中读取数据,构造方法如下,BufferedInputStream类继承自InputStream,所以该类的方法与InputStream类的方法相同。
pubic BufferedInputStream(InputStream in)
public BufferedInputStream(InputStream in,int size)
完成输出操作时,再将字节数据写入缓冲区,当缓冲区满时,再把缓冲区中的所有数据一次性写到输出流中,构造方法如下,BufferedOutputStream类继承自OutputStream类,所以该类的方法与OutputStream类的方法相同。
public BufferedOutputStream(OutputStream out)
public BufferedOutputStream(OutputStream out,int size)
(2)、字节缓冲IO类
BufferedReader类与字节缓冲输入流BufferedInputStream类在功能和实现上基本相同,但只适用于字符读入,构造方法如下,
BufferedReader类继承自Reader,所以该类的方法与Reader方法相同
public BufferedReader(Reader in)
public BufferedReader(Reader in,int sz)
BufferedWriter类与字节缓冲输出流BufferedOutputStream类在功能上和实现上是相同的,但只用于字符输出,BufferedWriter类继承自Write类,所以该类的方法与Write类的方法相同。
public BufferedWriter(Write out)
public BufferedWriter(Write out,int sz)
向指定文件写入内容,并重新读取该文件内容
public class Test{
public static void main(String[] args) {
File file;
FileReader fin;
FileWriter fout;
BufferedReader bin;
BufferedWriter bout;
Scanner scanner = new Scanner(System.in);
System.out.println("请输入文件名:");
String filename = scanner.nextLine();
try {
file = new File(filename);
if(!file.exists()) {
file.createNewFile(); //创建新文件
fout = new FileWriter(file); //创建文件输出流对
}
else {
fout = new FileWriter(file,true); //创建追加内容的文件输出流对象
fin = new FileReader(file); //创建缓冲输入流
bin = new BufferedReader(fin);
bout = new BufferedWriter(fout); //创建缓冲输出流
System.out.println("请输入数据,最后一行为字符“0”结束");
String str = scanner.nextLine();//从键盘读取待输入字符串
while(!str.equals("0")) {
bout.write(str); //输出字符串内容
bout.newLine(); //输出换行符
str = scanner.nextLine(); //读下一行
}
bout.flush(); //刷新输出流
bout.close(); //关闭缓冲输出流
fout.close(); //关闭文件输出流
System.out.println("文件写入完毕!");
//重新将文件内容显示出来
System.out.println("文件 "+filename+" 的内容是");
while((str = bin.readLine())!=null)
System.out.println(str); //读取文件内容并显示
bin.close(); //关闭文件输出流
fin.close(); //关闭文件输入流
}
}
catch(IOException e){
e.printStackTrace();
}
}
}
输出:
请输入文件名:
D:\FileInputStream\Test.txt
请输入数据,最后一行为字符“0”结束
hello
0
文件写入完毕!
文件 D:\FileInputStream\Test.txt 的内容是
hello
7、打印流
(1)、PrintStream类
PrintStream类提供了一系列的print()和printIn()方法,可以实现将基本数据类型的格式转换成字符串输出,PrintStream有三种构造方法
PrintStream(OutputStream out)
PrintStream(OutputStream out.boolean autoflush)
PrintStream(OutputStream out.boolean autoflush,String encoding)
-
autoflush控制在Java中遇到换行符是否自动清空缓冲区
-
encoding指定编码方式
print()和printIn()方法的区别是:print()会再打印完完的内容后面再打印一个换行符,所以print()等于print("\n")
(2)、PrintWriter类
I/O包中提供了一个与PrintStream对应的PrintWriter类,PrintWriter有四种构造方法
PrintWriter(OutputStream)
PrintWriter(OutputStream,boolean)
PrintWriter(Writer)
PrintWriter(Writer,boolean)
通过PrintWriter类向屏幕输出信息
import java.io.PrintWriter;
class StreamTest {
public static void main(String[] args) {
PrintWriter out = null;
//通过System.out对PrintWriter实例化
out = new PrintWriter(System.out);
//向屏幕输出
out.print("Hello world");
out.close();
}
}
输出:
Hello world
通过PrintWriter向文件中输出信息
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
class StreamTest {
public static void main(String[] args) {
PrintWriter out = null;
File f =new File("D:\\FileInputStream\\demo");
try {
out = new PrintWriter(new FileWriter(f));
}
catch(IOException e) {
e.printStackTrace();
}
//由于FileWriter类实例化,则向文件中输出
out.print("Hello world"+"\r\n");
out.close();
}
}
输出:
8、数据操作流
1、数据输入流
数据输入流DataInputStream类允许程序以预计其无关的方式从底层输入流中读取基本Java数据类型。
2、数据输出流
数据输入流DataOutputStream类允许程序以适当的方式将基本Java数据类型写入输出流。
9、系统流
(1)、系统标准IO流
System.in是一个键盘输入流,是InputStream类的对,在Java中,可以使用它从键盘读取数据
import java.io.IOException;
import java.io.InputStream;
public class Test{
public static void main(String[] args) throws IOException {
InputStream input = System.in;
byte b[] = new byte[5];
System.out.println("请输入内容:");
int len = input.read(b);
System.out.println("您输入的内容为:"+new String(b,0,len));
input.close();
}
}
输出:
请输入内容:
12345
您输入的内容为:12345
System.out是printStream类的对象,在printStream类中定义了一些列的pint()和println()方法,用来向显示器输出信息
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
public class Test{
public static void main(String[] args) throws Exception {
File f = new File("D:\\FileInputStream"+File.separator+"test.txt");
Reader input = null;
input = new FileReader(f);
char c[] = new char[1024];
int len = input.read(c);
input.close();
System.out.println("内容为:"+new String(c,0,len));
}
}
输出:
内容为:hello
next():
-
1、一定要读取到有效字符后才可以结束输入。
-
2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
-
3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
-
4、next() 不能得到带有空格的字符串。
nextLine():
-
1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
-
2、可以获得空白。
(2)、错误信息输出流
System.err用来实现错误信息输出,如果程序错误则可直接用System.err输出错误信息
public class Test{
public static void main(String[] args) {
String str = "Hello";
try {
System.out.println(Integer.parseInt(str));
}catch(Exception e) {
System.out.println(e);
}
}
}
输出:
java.lang.NumberFormatException: For input string: "Hello"
二、内存流
1、字节流
ByteArrayInputStream是输入流的一种实现,有两个构造方法,都需要一个字节数组来作为其数据源
ByteArrayInputStream(byte[] buf)
ByteArrayInputStream(byte[] buf,int offset,int length)
ByteArrayOutputStream()
ByteArrayOutputStream(int)
ByteArrayInputStream类的使用
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class Test{
public static void main(String[] args) throws Exception{
String tmp = "qwertyuiopasdfghjklzxcvbnm";
byte[] src = tmp.getBytes();
ByteArrayInputStream input = new ByteArrayInputStream(src);
ByteArrayOutputStream output = new ByteArrayOutputStream();
new Test().transform(input,output);
byte[] result = output.toByteArray();
System.out.println(new String(result));
}
public void transform(ByteArrayInputStream input, ByteArrayOutputStream output) {
int c =0;
try {
while((c = input.read())!=-1)
{
int C = (int) Character.toUpperCase((char) c);
output.write(C);
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}
输出: QWERTYUIOPASDFGHJKLZXCVBNM
2、字符流
CharArrayReader类是字符数组输入流,用于读取字符数组。CharArrayReader继承Reader类,操作的数据以字符为单位
CharArrayWriter类是字符数组输出流,主要用于输出字符数组,继承Writer类,操作的数据是以字符为单位
-
CharArrayReader实际上是通过字符数组保存数据的
-
在构造函数中有buf,通过buf来创建对象
-
read()函数读取下一个字符
字符数组应用
import java.io.CharArrayReader;
import java.io.IOException;
public class Test{
private static final int LEN =5;
//对应英文字母“abcdefghijklmnopqrstuvwxyz”
private static final char[] ArrayLetters = new char[] {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
public static void main(String[] args) {
tesCharArrayReader();
}
/*
* CharArrayReader的API测试函数
*/
private static void tesCharArrayReader() {
try {
CharArrayReader car = new CharArrayReader(ArrayLetters);
//从字符数组流中读取5个字符
for(int i = 0; i<LEN;i++) {
//若能继续读取下一字符,则读取下一字符
if(car.ready() == true) {
//读取字符流的下一个字符
char tmp = (char)car.read();
System.out.printf("%d : %c\n",i,tmp);
}
}
//若该字符流不支持表记功能,则直接退出
if(!car.markSupported()) {
System.out.println("make not supported");
return;
}
car.mark(0);
car.skip(5);
char[] buf = new char[LEN];
car.read(buf,0,LEN);
System.out.printf("buf = %s\n",String.valueOf(buf));
}catch(IOException e) {
e.printStackTrace();
}
}
}
输出:
0 : a
1 : b
2 : c
3 : d
4 : e
buf = klmno
3、字符串流
BufferedReader类是Reader类的子类,使用该类可以以行为单位读取数据,BufferedReader类主要构造方法如下:
BufferedReader(Reader in)
该构造方法使用Reader类的对象创建一个BufferedReader对象,语法如下:
new BufferedReader(in);
BufferedReader类中提供了ReaderLine()方法,Reader类中没有该方法。该方法能够读取文本行,比如:
import java.io.BufferedReader;
import java.io.FileReader;
public class Test{
public static void main(String[] args) {
FileReader fr;
try {
fr = new FileReader("D:\\FileInputStream\\demo.txt");
BufferedReader br = new BufferedReader(fr);
String aline;
while((aline = br.readLine())!=null) {
String str = new String(aline);
System.out.println(str);
}
fr.close();
br.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
输出: Hello world
BufferedWriter类是Writer类的子类,该类可以以行为单位写入数据,常用构造方法为:
BufferedWriter(Writer out)
该构造方法使用Writer类的对象来创建一个BufferedWriter对象,语法格式如下:
new BufferedWriter(out)
BufferedWriter类中提供了newLine()方法,Writer类中没有该方法。该方法是换行标记,比如:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
public class Test{
public static void main(String[] args) {
File file = new File("D:\\FileInputStream\\demo.txt");
FileWriter fos;
try {
fos = new FileWriter(file,true);
BufferedWriter bw = new BufferedWriter(fos);
bw.write("Example");
bw.newLine();
bw.write("Example");
bw.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
4、扫描流
(1)、输入各类数据
使用Scanner类实现基本的数据输入
(2)、读取文件内容
Scanner类还可以读取文件内容
5、对象序列化
序列化简单说就是为了保存在内存中的各种对象的状态,并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存Object States,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
什么情况下需要序列化
-
当你想把的内存中的对象保存到一个文件中或者数据库中时候;
-
当你想用套接字在网络上传送对象的时候;
-
当你想通过RMI传输对象的时候;
(1)、使用对象流实现序列化
序列化步骤:
-
创建一个ObjectOutputStream,这个输出流是一个处理流,所以必须建立在其他节点流的基础之上。
-
调用ObjectOutputStream对象的writeObject()方法输出可序列化对象。
定义一个普通的Java类,只是实现了Serializable接口,该接口标识该类的对象是可序列化的。
public class Canine implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
public Canine(String name) {
this.name = name; }
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
main.java
public class ObjectStreamTest {
public static void main(String[] args) {
try(
FileOutputStream outputStream = new FileOutputStream("src\\com\\rrz\\object.txt");
ObjectOutputStream oOut = new ObjectOutputStream(outputStream);
) {
oOut.writeObject(new Canine("狮子"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
反序列化步骤:
从二进制流中恢复 java 对象
-
创建一个ObjectInputStream输入流,这个输入流是一个处理流,所以必须建立在其他节点流的基础之上。
-
调用ObjectInputStream对象的readObject()方法读取流中的对象,该方法返回一个Object类型的Java对象,如果程序知道该Java对象的类型,则可以将该对象强制类型转换成其真实的类型。
public class Canine implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
public Canine(String name) {
System.out.println("这是一个有参数的构造器");
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
main.java
public class ObjectStreamTest {
public static void main(String[] args) {
try(
FileInputStream inputStream = new FileInputStream("src\\com\\rrz\\object.txt");
ObjectInputStream in = new ObjectInputStream(inputStream);
) {
Canine object = (Canine) in.readObject();
System.out.println(object.getName());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
(2)、transient关键字
Serializable接口实现的操作实际上是将一个对象中的全部属性序列化,当进行序列化操作时,如果一个对象中的某个属性不希望被序列化,则可用使用transient声明
class Person implements Serializable{
//Person类的对象可以被序列化
private transient String name;
//name属性将不被序列化
private int age;
//age属性将被序列化
public Person(String name,int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "姓名:"+this.name+"年龄:"+this.age;
}
}