黑马程序员
1. IO流概念
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的对象都在IO包中
流按流向分为两种:输入流,输出流。
流按操作类型分为两种:字节流与字符流。 字节流可以操作任何数据,字符流只能操作纯字符数据,比较方便。
2. IO流常用基类
字节流的抽象基类:
InputStream ,OutputStream
字符流的抽象基类:
Reader , Writer
由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
如:InputStream的子类FileInputStream。
如:Reader的子类FileReader。
注意: InputStreamReader 是字符流, 可以从字节流中读取字符
import java.io.FileWriter;
import java.io.IOException;
public class WriterDemo {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("dest.txt", true); // 文件不存在时创建, 存在则清空
fw.write("向文件中添加内容\r\n");
fw.close();
}
}
import java.io.FileReader;
import java.io.IOException;
public class ReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("test.txt");
int c;
while ((c = fr.read()) != -1)
System.out.print((char) c);
fr.close();
}
}
3. IO程序书写
使用前,导入IO包中的类
使用时,进行IO异常处理
使用后,释放资源
import java.io.*;
class FileWriterDemo
{
public static void main(String[] args) throws IOException
{
/*
需求:通过字符写入流将数据写入到一个文件中。
使用FileWriter对象完成。
该对象一创建就必须明确数据要存放位置。
*/
//创建FileWriter对象。在堆内存中定义了一个对象实例。
//同时调用了系统资源,在执行位置创建了一个文件。用于存储数据。
/*
当指定目录下已有该文件,会被覆盖。
如果构造函数中传入true,那么可完成对已有文件数据续写。
*/
FileWriter fw = new FileWriter("a.txt",true);
//使用Writer中的write方法,写入数据。
//将数据写入到了流中。
fw.write("\r\nhello");
//close()用于关闭资源,但在关闭前,会先刷新缓冲区,将缓冲区中的数据刷到目的地。
fw.close();
//刷新缓冲区。flush
/*fw.flush();
fw.write("kkkkk");
fw.flush();
//关闭资源。
fw.close();
fw.write("haha");
*/
}
}
4. 字符流读写文件
读取文件
定义字符流关联指定文件
FileReader reader = new FileReader("Test.txt");
读取一个字符,返回int,该字符的码表值
int ch = reader.read();
关闭流,释放资源
reader.close();
import java.io.*;
class FileReaderDemo
{
public static void main(String[] args) throws IOException
{
//创建字符读取流对象,并关联指定文件数据。
FileReader fr = new FileReader("a.txt");
int ch = 0;
while((ch=fr.read())!=-1)
{
System.out.println((char)ch);
}
fr.close();
}
}
定义字符输出流关联指定文件
FileWriter writer = new FileWriter("Test.txt");
写出一个字符,接收int码表值
writer.write(97);
关闭流,释放资源
writer.close();
注意事项
文件路径
定义文件路径时Windows中的目录符号为“\”,但这个符号在Java中是特殊字符,需要转义。
可以用“\\”或“/”表示。
读取文件
读取文件时必须保证文件存在,否则将抛出FileNotFoundException。
写出文件
写出时文件如不存在时程序会创建新文件,如文件已存在则会清空原文件内容重新写入。
如需追加内容可调用FileWriter构造函数FileWriter(String fileName, boolean append)
import java.io.FileWriter;
import java.io.IOException;
public class WriterDemo {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("dest.txt", true); // 文件不存在时创建, 存在则清空
fw.write("向文件中添加内容\r\n");
fw.close();
}
}
5. 字符流缓冲区读写
自定义缓冲区读写
为什么定义缓冲区
由于单个字符读写需要频繁操作文件,所以效率非常低。
我们可以定义缓冲区将要读取或写出的数据缓存,减少操作文件次数。
缓冲区读取
先定义一个数组,然后调用FileReader读取一个数组的方法。
int read(char[] cbuf)
缓冲区写出
将要写出的数据存放在数组中,调用FileWriter方法,一次写出一个数组。
void write(char[] cbuf, int off, int len)
内置缓冲区的BufferedReader和BufferedWriter
Java提供了带缓冲功能的Reader和Writer类:BufferedReader,BufferedWriter
这两个类都是提供包装功能,需要提供其他流来使用,给其他流增加缓冲功能
当我们调用BufferedReader读取数据时,程序会从文件中一次读取8192个字符用来缓冲
当我们调用BufferedWriter写出数据时,程序会先将数据写出到缓冲数组,直到写满8192个才一次性刷出到文件
import java.io.IOException;
import java.io.Writer;
public class MyBufferedWriter extends Writer {
private Writer writer;
private char[] buffer = new char[8192];
private int len;
public MyBufferedWriter(Writer writer) {
this.writer = writer;
}
/*
* 判断缓冲区是否写满, 如果写满则将缓冲区数据写出.
* 如果缓冲区没有写满, 就先写到缓冲区中
*/
public void write(int c) throws IOException {
if (len == buffer.length)
flush();
buffer[len++] = (char) c;
}
/*
* 释放资源, 并且将缓冲区的内容刷出
*/
public void close() throws IOException {
flush();
writer.close();
}
/*
* 将缓冲区中的数据刷出, 写到被包装的输出流中
*/
public void flush() throws IOException {
writer.write(buffer, 0, len);
len = 0;
}
/*
* 写出一个字符串, 将字符串转为字符数组, 遍历数组逐个写出
*/
public void write(String line) throws IOException {
for (char c : line.toCharArray())
write(c);
}
/*
* 写出换行符号
*/
public void newLine() throws IOException {
write("\r\n");
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
for (int i = off; i < off + len; i++)
write(cbuf[i]);
}
}
import java.io.IOException;
import java.io.Reader;
/*
* 在调用read()方法时, 判断缓冲区中是否有有效数据, 有则直接返回缓冲区中的, 没有就从被包装流中读取数据到缓冲区再返回
*/
public class MyBufferedReader extends Reader {
private Reader reader; // 被包装的流
private char[] buffer = new char[8192]; // 缓冲区
private int pos; // 读取的位置
private int len; // 有效数据的个数
public MyBufferedReader(Reader reader) { // 通过构造函数包装一个流
this.reader = reader;
}
public int read() throws IOException {
if(pos == len){ // 第一次调用read()方法 或者 所有有效数据都被读取过
len = reader.read(buffer);
pos = 0;
}
return len == -1 ? -1 : buffer[pos++];
}
public void close() throws IOException{
reader.close();
}
public String readLine() throws IOException {
StringBuilder sb = new StringBuilder();
int ch;
while (true) {
ch = read(); // 读取一个字符
if (ch == '\r' || ch == -1) // 判断是否是行末尾或文件末尾
break;
if (ch == '\n')
continue;
sb.append((char) ch);
}
return ch == -1 && sb.length() == 0 ? null : sb.toString();
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return 0;
}
}
6. 装饰设计模式(Decorator)
什么情况下使用装饰设计模式
当我们需要对一个类的功能进行改进、增强的时候
装饰模式的基本格式。
含有被装饰类的引用
通过构造函数传入被装饰类对象
和被装饰类含有同样的方法,其中调用被装饰类的方法,对其进行改进、增强
和被装饰类继承同一个类或实现同一个接口,可以当做被装饰类来使用
了解BufferedReader、BufferedWriter的原理。
BufferedReader、BufferedWriter都是装饰类,他们可以装饰一个Reader或Writer,给被装饰的Reader和Writer提供缓冲的功能。
就像我们用BufferedReader、BufferedWriter装饰FileReader和FileWriter,使用的读写功能还是FileReader和FileWriter的,但给这两个类的读写添加了缓冲功能。
练习
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
public class MyLineNumberReader extends BufferedReader {
private int lineNumber;
/*
* 创建LineNumberReader的时候, 需要接受一个Reader, 这个Reader将传入BufferedReader的构造函数中
*/
public MyLineNumberReader(Reader reader) {
super(reader);
}
public int getLineNumber() {
return lineNumber;
}
/*
* 调用该方法时, 使用BufferedReader的readLine()方法读取一行
* 判断如果不为空就将行号加1
*/
public String readLine() throws IOException {
String line = super.readLine();
if (line != null)
lineNumber++;
return line;
}
}
7. 字节流
基本操作与字符流相同
字节流可以操作任意类型数据
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
public class ConvertStream {
public static void main(String[] args) throws IOException {
// read3(new FileInputStream("day15-笔记.txt"));
write1(new FileOutputStream("dest.txt"));
}
/*
* 方法中获得了一个字节输出流, 想向流中写出字符数据
*/
private static void write1(OutputStream out) throws IOException {
out.write("字符数据".getBytes());
out.write("再写一次".getBytes());
out.close();
}
/*
* 将字节流转为字符流, 直接写出字符, 自动编码
*/
private static void write2(OutputStream out) throws IOException {
Writer writer = new OutputStreamWriter(out);
writer.write("字符数据");
writer.write("再写一次");
writer.close();
}
/*
* 该方法接收一个字节输入流(流中所有数据都是字符数据), 可以将流中的字符打印在屏幕上
*/
public static void read1(InputStream in) throws IOException {
int b;
while ((b = in.read()) != -1) {
byte b1 = (byte) b;
if (b1 < 0) {
byte b2 = (byte) in.read();
System.out.print(new String(new byte[] { b1, b2 }));
} else
System.out.print((char) b);
}
in.close();
}
/*
* 人工解码
* 需要考虑最后一个是否是中文的一半
*/
public static void read2(InputStream in) throws IOException {
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1)
System.out.print(new String(buffer, 0, len));
in.close();
}
/*
* 在方法中我们获得了一个字节流, 需要从中读取字符的时候, 就可以用转换流来做
* InputStreamReader可以从InputStream中读取字符
* 自动解码
*/
public static void read3(InputStream in) throws IOException {
Reader r = new InputStreamReader(in);
int ch;
while ((ch = r.read()) != -1)
System.out.print((char) ch);
r.close();
}
}
8. 字节流缓冲区读写
自定义缓冲区读写
原理和字符流相同,都是为了提高效率
定义数组缓冲数据,一次读取一个数组,一次写出一个数组,减少操作文件的次数
BufferedInputStream、BufferedOutputStream
和BufferedReader、BufferedWriter原理相同,都是包装类
BufferedInputStream、BufferedOutputStream包装InputStream和OutputStream提供缓冲功能
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
public class Review {
public static void main(String[] args) throws IOException {
// review1();
// review2();
// review3();
// review4();
}
private static void review4() throws FileNotFoundException, IOException {
BufferedReader r = null;
BufferedWriter w = null;
try {
r = new BufferedReader(new FileReader("IMG_0009.jpg"));
w = new BufferedWriter(new FileWriter("dest.jpg"));
String line;
while ((line = r.readLine()) != null) {
w.write(line);
w.newLine();
}
} finally {
Util.close(r, w);
}
}
private static void review3() throws FileNotFoundException, IOException {
Reader r = null;
Writer w = null;
try {
r = new BufferedReader(new FileReader("day15-笔记.txt")); // 读取的时候先读到缓冲区, 减少读文件的次数
w = new BufferedWriter(new FileWriter("dest.txt")); // 写出的时候, 先写到缓冲区, 减少操作文件的次数
int ch;
while ((ch = r.read()) != -1)
w.write(ch);
} finally {
Util.close(r, w);
}
}
private static void review2() throws FileNotFoundException, IOException {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("day15-笔记.txt");
fw = new FileWriter("dest.txt", true);
char[] buf = new char[1024];
int len;
while ((len = fr.read(buf)) != -1)
fw.write(buf, 0, len);
} finally {
Util.close(fr, fw);
}
}
private static void review1() throws FileNotFoundException, IOException {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("day15-笔记.txt");
fw = new FileWriter("dest.txt");
int ch;
while ((ch = fr.read()) != -1)
fw.write(ch);
} finally {
Util.close(fr, fw);
}
}
}
9. 转换流
字符流与字节流之间的桥梁
方便了字符流与字节流之间的操作
字节流中的数据都是字符时,转成字符流操作更高效
练习
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
public class ConvertStream {
public static void main(String[] args) throws IOException {
// read3(new FileInputStream("day15-笔记.txt"));
write1(new FileOutputStream("dest.txt"));
}
/*
* 方法中获得了一个字节输出流, 想向流中写出字符数据
*/
private static void write1(OutputStream out) throws IOException {
out.write("字符数据".getBytes());
out.write("再写一次".getBytes());
out.close();
}
/*
* 将字节流转为字符流, 直接写出字符, 自动编码
*/
private static void write2(OutputStream out) throws IOException {
Writer writer = new OutputStreamWriter(out);
writer.write("字符数据");
writer.write("再写一次");
writer.close();
}
/*
* 该方法接收一个字节输入流(流中所有数据都是字符数据), 可以将流中的字符打印在屏幕上
*/
public static void read1(InputStream in) throws IOException {
int b;
while ((b = in.read()) != -1) {
byte b1 = (byte) b;
if (b1 < 0) {
byte b2 = (byte) in.read();
System.out.print(new String(new byte[] { b1, b2 }));
} else
System.out.print((char) b);
}
in.close();
}
/*
* 人工解码
* 需要考虑最后一个是否是中文的一半
*/
public static void read2(InputStream in) throws IOException {
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1)
System.out.print(new String(buffer, 0, len));
in.close();
}
/*
* 在方法中我们获得了一个字节流, 需要从中读取字符的时候, 就可以用转换流来做
* InputStreamReader可以从InputStream中读取字符
* 自动解码
*/
public static void read3(InputStream in) throws IOException {
Reader r = new InputStreamReader(in);
int ch;
while ((ch = r.read()) != -1)
System.out.print((char) ch);
r.close();
}
}
10. 标准输入输出流
System类中的成员变量:in,out。
它们各代表了系统标准的输入和输出设备。
默认输入设备是键盘,输出设备是显示器。
System.in的类型是InputStream.
System.out的类型是PrintStream是OutputStream的子类FilterOutputStream 的子类.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/*
* System.in 是系统的标准输入流, 默认读取键盘输入数据, 是一个InputStream
* 如果我们想从键盘输入读取字符, 那么就可以使用InputStreamReader将System.in转为字符流
* 如果我们向一次从键盘输入中读取一行, 那么可以使用BufferedReader包装InputStreamReader
*/
public class ReadKeyInputDemo {
public static void main(String[] args) throws IOException {
InputStream in = System.in; // 获取系统默认输入流, InputStream
InputStreamReader isr = new InputStreamReader(in); // 为了读字符方便, 转换为Reader
BufferedReader br = new BufferedReader(isr); // 为了读一行, 转换为BufferedReader
// BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
}
}
11. 流基本应用小节
流是用来处理数据的。
处理数据时,一定要先明确数据源,或者数据目的地
数据源可以是文件,可以是键盘或者其他设备。
数据目的地可以是文件、显示器或者其他设备。
而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理、转换处理等。
12. File类
用来将文件或者文件夹路径封装成对象
方便对文件与文件夹进行操作。
File对象可以作为参数传递给流的构造函数。
了解File类中的常用方法。
File类的方法分类:
1,创建。
boolean createNewFile()throws IOException
static File createTempFile(String prefix, String suffix)
boolean mkdir()
boolean mkdirs()
2,删除。
boolean delete();
void deleteOnExit()
3,判断。
exists();
canExecute();
canRead();
canWrite();
isHidden();
isFile();
isDirectory();
isAbsolute();
4,获取。
getName();
getPath();
getParent();
getAbsolutePath();
long lastModified()
返回此抽象路径名表示的文件最后一次被修改的时间。
long length()
String[] list();
File[] listFiles();
import java.io.File;
public class FileDemo {
public static void main(String[] args) {
// test1();
// test2();
// test3();
// test4();
// test5();
}
private static void test5() {
File parent = new File("F:/Itcast/20111015");
File f1 = new File(parent, "day4");
File f2 = new File(parent, "day5");
File f3 = new File(parent, "day6");
File f4 = new File(parent, "1015课表.xls");
File f5 = new File(parent, "cmd.exe");
System.out.println(f1.exists());
System.out.println(f2.exists());
System.out.println(f3.exists());
System.out.println(f4.exists());
System.out.println(f5.exists());
}
/*
* 字符串类型父级路径
*/
private static void test4() {
String parent = "F:/Itcast/20111015";
File f1 = new File(parent, "day4");
File f2 = new File(parent, "day5");
File f3 = new File(parent, "day6");
File f4 = new File(parent, "1015课表.xls");
File f5 = new File(parent, "cmd.exe");
System.out.println(f1.exists());
System.out.println(f2.exists());
System.out.println(f3.exists());
System.out.println(f4.exists());
System.out.println(f5.exists());
}
/*
* 判断是否是绝对路径
*/
private static void test3() {
File f1 = new File("F:/Itcast/20111015/day16/day16-笔记.txt"); // 绝对路径, 从盘符开始
File f2 = new File("day16-笔记.txt");
System.out.println(f1.isAbsolute()); // 是否是绝对路径
System.out.println(f2.isAbsolute());
}
/*
* 判断是否是文件, 是否是文件夹
*/
private static void test2() {
File f1 = new File("day16-笔记.txt"); // 指向文件
File f2 = new File("src"); // 指向文件夹
System.out.println(f1.isFile()); // 判断是否是存在的文件
System.out.println(f2.isFile());
System.out.println(f1.isDirectory()); // 判断是否是存在的文件夹
System.out.println(f2.isDirectory());
}
/*
* File f2 = new File("day16-笔记.txt");
* 相对目录由运行环境不同而相对的路径也不同
* 在Eclipse中运行时是找工程根目录下的 day16-笔记.txt
* 在cmd中运行时是在当前目录下找 day16-笔记.txt
*/
private static void test1() {
File f1 = new File("F:/Itcast/20111015/day16/day16-笔记.txt"); // 绝对路径, 从盘符开始
File f2 = new File("day16-笔记.txt"); // 相对路径, 在Eclipse中相对于工程根目录, cmd相对于当前目录
System.out.println(f1.exists()); // 判断该File对象封装的路径是否存在
System.out.println(f2.exists());
}
}
13. 递归
函数自己调用自己。
注意:递归时一定要明确结束条件。
应用场景:
当某一功能要重复使用时。
练习:
列出一个文件夹下所有的子文件夹以及子文件
/*
listFiles可以列出当前目录下的文件以及文件夹。
需求:
想要列出指定目录下的所有文件以及文件夹,包含子文件夹中的内容。
递归:编程手法。
特点:方法自身调用自身。
注意:在递归时,两个注意事项:
1,一定要定义递归的条件。
2,要注意递归的次数。
public void show()
{
show();
}
*/
import java.io.*;
class FileDemo3
{
public static void main(String[] args)
{
File dir = new File("d:\\java0217");
//listAll(dir);
//toBin(6);
int num = getSum(30000);
System.out.println("num="+num);
}
public static int getSum(int num)
{
if(num==1)
return 1;
return num+getSum(num-1);
}
public static void toBin(int num)
{
if(num>0)
{
toBin(num/2);
System.out.println(num%2);
}
}
public static void listAll(File dir)
{
File[] files = dir.listFiles();
for(int x=0; x<files.length; x++)
{
if(files[x].isDirectory())
listAll(files[x]);
System.out.println(files[x]);
}
}
}
14. IO包中的其他类
序列流
SequenceInputStream
可以将多个字节输入流整合成一个流,在使用这个流读取的时候,读到第一个流的末尾时继续读第二个,第二个读到末尾则继续读第三个,以此类推,直到读到最后一个流的末尾返回-1
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
public class SequenceInputStreamDemo {
public static void main(String[] args) throws IOException {
// test1();
// test2();
// test3();
// test4();
}
private static <X> Enumeration<X> enumeration(final Collection<X> c) {
return new Enumeration<X>() {
Iterator<X> iter = c.iterator();
public boolean hasMoreElements() {
return iter.hasNext();
}
public X nextElement() {
return iter.next();
}
};
}
private static void test4() throws FileNotFoundException, IOException {
FileInputStream fis1 = new FileInputStream("1.txt");
FileInputStream fis2 = new FileInputStream("2.txt");
FileInputStream fis3 = new FileInputStream("3.txt");
ArrayList<FileInputStream> list = new ArrayList<FileInputStream>();
Collections.addAll(list, fis1, fis2, fis3); // 添加3个输入流
Enumeration<FileInputStream> e = Collections.enumeration(list); // 从List获取Enumeration
SequenceInputStream sis = new SequenceInputStream(e); // 整合
FileOutputStream fos = new FileOutputStream("4.txt");
byte[] buf = new byte[1024];
int len;
while((len = sis.read(buf)) != -1)
fos.write(buf, 0, len);
sis.close(); // 这里会关闭被整合的流
fos.close();
}
private static void test3() throws FileNotFoundException, IOException {
FileInputStream fis1 = new FileInputStream("1.txt");
FileInputStream fis2 = new FileInputStream("2.txt");
FileInputStream fis3 = new FileInputStream("3.txt");
Vector<FileInputStream> v = new Vector<FileInputStream>(); // 为了获取Enumeration, 创建Vector
v.add(fis1);
v.add(fis2);
v.add(fis3);
Enumeration<FileInputStream> e = v.elements(); // 获取Enumeration
SequenceInputStream sis = new SequenceInputStream(e); // 整合
FileOutputStream fos = new FileOutputStream("4.txt");
byte[] buf = new byte[1024];
int len;
while((len = sis.read(buf)) != -1)
fos.write(buf, 0, len);
sis.close(); // 这里会关闭被整合的流
fos.close();
}
private static void test2() throws FileNotFoundException, IOException {
FileInputStream fis1 = new FileInputStream("1.txt");
FileInputStream fis2 = new FileInputStream("2.txt");
FileInputStream fis3 = new FileInputStream("3.txt");
SequenceInputStream sis1 = new SequenceInputStream(fis1, fis2); // 整合1,2
SequenceInputStream sis2 = new SequenceInputStream(sis1, fis3); // 将1,2和3整合
FileOutputStream fos = new FileOutputStream("4.txt");
byte[] buf = new byte[1024];
int len;
while((len = sis2.read(buf)) != -1)
fos.write(buf, 0, len);
sis2.close(); // 这里会关闭被整合的流
fos.close();
}
private static void test1() throws FileNotFoundException, IOException {
FileInputStream fis1 = new FileInputStream("1.txt");
FileInputStream fis2 = new FileInputStream("2.txt");
SequenceInputStream sis = new SequenceInputStream(fis1, fis2); // 创建序列流, 整合2个输入流
FileOutputStream fos = new FileOutputStream("3.txt");
byte[] buf = new byte[1024];
int len;
while((len = sis.read(buf)) != -1)
fos.write(buf, 0, len);
sis.close(); // 这里会关闭被整合的流
fos.close();
}
}
打印流
PrintStream 、PrintWriter
相比普通的OutputStream和Writer增加了print()和println()方法,这两个方法可以输出实参的toString()方法的返回值
这两个类还提供自动flush()的功能
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import cn.itcast.day17.domain.Person;
/*
* 00000000 00000000 00000000 01100001 97
* 00000000 00000000 01101010 01100001 27233
*
* ps.print(i);
*
* Integer integer = new Integer(i)
* ps.print(integer.toString());
*
* 如果我们需要输出一个对象的toString()返回值时使用
* 在每次写出之后时需要flush()时使用
* 在每次写出之后需要换行时使用
*/
public class PrintStreamDemo {
public static void main(String[] args) throws Exception {
// test1();
// test2();
// test3();
// test4();
}
private static void test4() throws FileNotFoundException, UnsupportedEncodingException {
FileOutputStream fos = new FileOutputStream("dest.txt");
PrintStream ps = new PrintStream(fos, true, "GBK"); // 包装字节流, 每次写出时flush(), 指定码表
ps.println(123);
ps.println("中文");
ps.close();
}
private static void test3() throws Exception {
Person p = new Person("沙诗博", 22);
int i = 27233;
PrintStream ps = new PrintStream("dest.txt", "UTF-8");
ps.println(i); // 写出的是实参对象的toString()返回值, 基本数据类型会先转成包装类对象
ps.println(p);
ps.close();
}
private static void test2() throws IOException {
int i = 27233;
FileWriter fw = new FileWriter("dest.txt");
fw.write(i); // 字符流写出, 先转char再写出
fw.close();
}
private static void test1() throws FileNotFoundException, IOException {
int i = 27233;
FileOutputStream fos = new FileOutputStream("dest.txt");
fos.write(i); // 字节输出流, 每次写出一个字节, 会将int类型的实参转为byte类型写出
fos.close();
}
}
操作对象
ObjectOutputStream
可以将实现了Serializable的接口的对象转成字节写出到流中
ObjectInputStream
可以从流中读取一个ObjectOutputStream流写出的对象
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import cn.itcast.day17.domain.Person;
/*
* 如果要将一个对象写出, 必须将其序列化.
* 序列化: 将对象转为可传输或存储的形式. 把对象转为字节数据.
*
* 将对象持久化的一种方式
*/
public class ObjectStreamDemo {
public static void main(String[] args) throws Exception {
// test1();
// test2();
// test3();
// test4();
// test5();
// test6();
}
private static void test6() throws IOException, FileNotFoundException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dest.txt"));
ArrayList<Person> list = (ArrayList<Person>) ois.readObject(); // 一次读取一个容器
ois.close();
for (Person p : list)
System.out.println(p); // 遍历容器得到每一个对象
}
private static void test5() throws IOException, FileNotFoundException {
Person p1 = new Person("沙 ", 22);
Person p2 = new Person(" 成龙", 23);
Person p3 = new Person("高 ", 24);
ArrayList<Person> list = new ArrayList<Person>(); // 创建一个容器
Collections.addAll(list, p1,p2,p3); // 将多个对象装入容器
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dest.txt"));
oos.writeObject(list); // 一次性写出
oos.close();
}
private static void test4() throws IOException, FileNotFoundException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dest.txt"));
System.out.println(ois.readObject());
System.out.println(ois.readObject());
System.out.println(ois.readObject());
ois.close();
}
// 写出多个对象
private static void test3() throws IOException, FileNotFoundException {
Person p1 = new Person("沙 ", 22);
Person p2 = new Person(" 成龙", 23);
Person p3 = new Person("高 ", 24);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dest.txt"));
oos.writeObject(p1);
oos.writeObject(p2);
oos.writeObject(p3);
oos.close();
}
private static void test2() throws IOException, FileNotFoundException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("dest.txt"));
Person p = (Person) ois.readObject(); // 读取一个对象
System.out.println(p);
ois.close();
}
private static void test1() throws IOException, FileNotFoundException {
Person p = new Person("沙 ", 22);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("dest.txt"));
oos.writeObject(p); // 写出对象
oos.close();
}
}
操作内存缓冲数组
ByteArrayOutputStream: 写出到字节数组(内存)中,可以获取写出的内容装入一个字节数组。通常我们用这个流来缓冲数据。
ByteArrayInputStream:可以从一个字节数组中读取字节。
CharArrayWriter:写出字符到字符数组(内存)中,可以获取写出的内容装入一个字符数组。
CharArrayReader:可以从一个字符数组中读取字符。
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* ByteArrayOutputStream 通常用来缓存数据, 可以把数据暂时写到内存中
*/
public class ByteArrayOutputStreamDemo {
public static void main(String[] args) throws IOException {
// test1();
// test2();
}
private static void test2() throws FileNotFoundException, IOException {
// 将流中所有数据都写到内存中
FileInputStream fis = new FileInputStream("day17-笔记.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;
while((len = fis.read(buf))!=-1)
baos.write(buf,0,len);
fis.close();
baos.close();
// 将字节数据转为字符串
String s = new String(baos.toByteArray());
System.out.println(s);
}
private static void test1() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("day17-笔记.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 数据目的地为内存
byte[] buf = new byte[1024];
int len;
while((len = fis.read(buf))!=-1)
baos.write(buf,0,len); // 写出数据到内存中
fis.close();
baos.close();
byte[] data = baos.toByteArray(); // 获取之前写出的所有数据
FileOutputStream fos = new FileOutputStream("dest.txt");
fos.write(data); // 将内存中所有数据一次性写出到文件
fos.close();
}
}
管道流
PipedInputStream:管道输入流,可以从管道输出流中读取数据
PipedOutputStream:管道输出流,可以向管道输入流中写出数据
操作基本数据类型
DataInputStream、DataOutputStream
可以按照基本数据类型占用空间大小读写数据
随机访问文件
RandomAccessFile
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
public class PipedStreamDemo {
public static void main(String[] args) throws IOException {
// test1();
// test2();
}
private static void test2() throws IOException {
PipedInputStream pis = new PipedInputStream(); // 创建管道输入流
PipedOutputStream pos = new PipedOutputStream(); // 创建管道输出流
pis.connect(pos); // 将输入流和输出流连接
PrintStream ps = new PrintStream(pos);
BufferedReader br = new BufferedReader(new InputStreamReader(pis));
ps.println("你好啊!"); // 管道输出流写出
System.out.println(br.readLine()); // 管道输入流读取
ps.println("再见!");
System.out.println(br.readLine());
ps.close();
br.close();
}
private static void test1() throws IOException {
PipedInputStream pis = new PipedInputStream(); // 创建管道输入流
PipedOutputStream pos = new PipedOutputStream(); // 创建管道输出流
pis.connect(pos); // 将输入流和输出流连接
pos.write("hi\r\n".getBytes()); // 使用输出流输出数据, 数据将流向输入流中
pos.write("bye".getBytes());
pos.close();
int b;
while((b = pis.read()) != -1)
System.out.print((char)b);
pis.close();
}
}